Skip to content

[BUG] edit_note with memory:// URL silently creates phantom notes instead of routing to the target project #1066

Description

@phernandez

Summary

edit_note with a memory:// URL identifier does not route to the target workspace/project — it treats the URL path as a relative file path and, because append creates missing notes, silently creates a phantom note in the session's default project. Found while editing a spec note during a working session (dogfood).

Repro (against cloud workspace basic-memory-7020…, note living in project specs at active/SPEC-55- Agent Memory Pipeline (Producer Framework).md)

  1. read_note(identifier="memory://<ws>/basic-memory-llc/specs/active/spec-55-agent-memory-pipeline-producer-framework") → resolves and returns the note (fuzzy fallback finds it even though the project segment is wrong — read is forgiving).
  2. edit_note(identifier=<same memory:// URL>, operation="append", …) on the local MCP server → "Ambiguous Identifier" error whose suggested retry list includes the plain memory:// form.
  3. Retrying with exactly that suggested memory:// form → fileCreated: true — a new note is created in the session's default project with the entire URL path as its file path. Same behavior via the cloud MCP server.
  4. edit_note(identifier="specs/active/spec-55-…", workspace="<ws>", project="basic-memory-llc")Entity with external_id 'e25141e2-…' not found (resolution produced an id that then 404s, instead of a "no such note in this project" message).
  5. Only edit_note(identifier="active/spec-55-…", project_id="<specs project uuid>") worked.

Problems

  1. Silent wrong-project note creation (worst): append's create-if-missing combined with an unrouted memory:// identifier writes a phantom note into whatever project the session defaults to. An identifier that looks like a memory:// URL but fails to route should be an error, never a relative-path create. (Cleanup required deleting two phantom notes.)
  2. The ambiguity error recommends the form that then misbehaves: step 2's suggestion list offers the plain memory:// identifier as a valid retry, which is exactly the form that creates phantoms in step 3.
  3. Unhelpful failure in the legit-params path: step 4 surfaces a raw external_id … not found instead of telling the user the note doesn't exist under that project (the note was in a sibling project; a "not found in project X — did you mean project Y?" or at least a clean not-found would have redirected immediately).

Expected

  • edit_note routes memory:// URLs exactly like read_note does, or rejects them with a clear error.
  • append/prepend never create a note when the identifier was a routing-style URL that failed to resolve.
  • Cross-project not-found errors name the project searched rather than leaking an internal external_id.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions