Skip to content

Workspace project index never refreshes on miss — out-of-band/teammate-created projects invisible and unroutable by project_id in running sessions #956

@phernandez

Description

@phernandez

Summary

The per-session workspace project index is built once and never refreshed on lookup miss. A cloud project created out-of-band (via CLI, another client, or — the worst case — a teammate in a shared team workspace) is invisible to every already-running MCP session:

  • list_memory_projects omits it
  • project_id routing hard-errors: Project '<uuid>' was not found in indexed cloud workspaces — asserting nonexistence of a project that demonstrably exists
  • read_note's fuzzy-fallback breaks even when the caller's project name resolves fine, because the fallback internally re-resolves via project_id

Reproduction (one session, minutes apart)

  1. MCP session running (local stdio, OAuth). Create a project out-of-band:
    bm project add manual --cloud --workspace <team-slug> --visibility shared
  2. In the running session:
    • search_notes(project="manual", query="x")works (name resolves via local config per-project routing)
    • search_notes(project_id="0e6a327b-...", query="x")error: Project '0e6a327b-...' was not found in indexed cloud workspaces. Available projects: <stale list omitting manual>
    • read_note("fuzzy text", project="manual")error (same), because the fallback at mcp/tools/read_note.py:319 passes project_id=active_project.external_id to search_notes, and project_id takes precedence — so the already-successfully-resolved project gets re-resolved through the stale index and dies
    • list_memory_projects() → stale list, no manual

The same asymmetry means a teammate adding a project to a shared workspace is invisible (and unroutable by project_id) to everyone's long-running sessions — e.g. Claude Desktop sessions that stay up for days.

Root cause

src/basic_memory/mcp/project_context.py:

  • The index is cached in FastMCP context state under _WORKSPACE_PROJECT_INDEX_STATE_KEY (~line 728/787) with no TTL
  • resolve_workspace_project_identifier() (~line 801) looks up the cached index and on miss raises ValueError (~line 881) with no attempt to rebuild
  • invalidate_workspace_project_index() exists but is only called after in-session create_memory_project — out-of-band creation has no invalidation path

Expected

Cache-miss refresh: when an external_id / qualified-name lookup misses the cached index, rebuild the index once and retry before raising. (Optionally also a short TTL, but miss-refresh alone fixes the correctness issue — a miss is exactly the signal that the cache may be stale.)

Also worth fixing alongside: read_note's fallback should not re-resolve a project it already holds — it has active_project in hand and could pass routing through directly.

Severity

High for Teams: shared-workspace project creation is a core flow, and the failure mode is a confident wrong answer ("project does not exist") rather than a miss.

Context

Found during live verification for #952. Related: #954 (create_memory_project workspace routing) — same discovery session.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingcloudBasic Memory Cloudneeds investigationIssue needs further investigation and/or refinement
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions