[Bug] Scoped search always returns 0 results (metadata filter silently dropped by /v4/search) + forget tool 404s on search result IDs
Summary
Two closely related bugs in opencode-supermemory (tested on v2.0.11, OpenCode 1.18.11, Windows):
- Scoped search returns 0 — calling the
supermemory tool in search mode with scope: "project" (or "user") always returns count: 0, even when memories exist and are returned by list with the same scope. The root cause is server-side: POST /v4/search silently returns zero results when a metadata filter (filters: {AND:[{key:"sm_scope",...}]}) is present, while POST /v3/documents/list with the identical filter works fine.
forget tool 404s on IDs returned by search — the plugin's forget mode calls memories.delete(id) which maps to DELETE /v3/documents/{id} (a document endpoint), but search returns memory-entity IDs (v4). The two ID spaces are different, so deleting a search result always fails with 404 Document not found. Only IDs from list (document IDs) can be forgotten.
Environment
- Plugin:
opencode-supermemory 2.0.11
- OpenCode: 1.18.11 (Windows, TUI)
- Model:
opencode-go/deepseek-v4-flash via custom gateway
- Container:
repo_plugin_lab__09b00afed75e0e2d (canonical project container)
Repro
Bug 1 — scoped search returns 0
supermemory search scope=project query="JetBrains MCP server port configuration IDEA CLion"
→ {"count": 0}
supermemory list scope=project
→ 2 memories (both about JetBrains MCP), verified present
Direct API calls with the real API key (from ~/.supermemory-opencode/credentials.json):
# WITHOUT filter → 5 results, similarity 0.885–0.946 (memories found, embedding + CJK matching all fine)
curl -X POST https://api.supermemory.ai/v4/search \
-H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
-d '{"q":"JetBrains MCP 端口配置 IDEA CLion","containerTag":"repo_plugin_lab__09b00afed75e0e2d","threshold":0.6,"limit":5,"searchMode":"hybrid"}'
# → total: 5
# WITH the plugin's exact filter → 0 results
curl -X POST https://api.supermemory.ai/v4/search \
-H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
-d '{"q":"JetBrains MCP 端口配置 IDEA CLion","containerTag":"repo_plugin_lab__09b00afed75e0e2d","threshold":0.6,"limit":5,"searchMode":"hybrid","filters":{"AND":[{"key":"sm_scope","value":"project","filterType":"metadata"}]}}'
# → total: 0
# Control: SAME filter shape works on the list endpoint
curl -X POST https://api.supermemory.ai/v3/documents/list \
-H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
-d '{"containerTags":["repo_plugin_lab__09b00afed75e0e2d"],"filters":{"AND":[{"key":"sm_scope","value":"project","filterType":"metadata"}]},"limit":20}'
# → 2 documents (filter itself is valid)
Additional probes (all reproduce the 0-result behaviour on /v4/search):
sm_scope=personal → 0
sm_scope=user → 0
type=architecture (different metadata key) → 0
- Different filter shapes (
filterType omitted / changed) → 0
Bug 2 — forget 404s on search-result IDs
supermemory search query="mand mandatory" # returns garbage memory id LKdnux69sBPdtDSfYBchdw (sim 0.86)
supermemory forget memoryId="LKdnux69sBPdtDSfYBchdw"
→ {"success": false, "error": "404 {\"error\":\"Document not found\"}"}
Root cause confirmed in source (dist/index.js):
searchMemories → client.search.memories(...) → POST /v4/search (returns memory-entity IDs, e.g. mem_* style or opaque IDs)
deleteMemory → client.memories.delete(memoryId) → DELETE /v3/documents/{id} (expects a document ID)
The correct v4 forget endpoint is DELETE /v4/memories with {id, containerTag} (soft-delete) — the plugin never calls it. Deleting a memory that only exists as a v4 entity (e.g. extracted from a since-deleted document, or a corrupted entity) is therefore impossible through the plugin.
Expected behaviour
search with a scope should return the same memories that list with the same scope shows (either the server should honour metadata filters on /v4/search, or the plugin should fall back to unscoped search and filter client-side).
forget should accept v4 memory-entity IDs and call DELETE /v4/memories (with containerTag), not only v3 document IDs.
Impact
- Scoped recall (the plugin's default recall path via
getScopeFilters) is effectively broken for everyone — the agent sees "no relevant memories" on every scoped search while memories exist. The unscoped path (searchMemoriesMany over all read containers) works, which is why the bug is easy to miss.
- Corrupted/low-quality memories written by the cloud ingestion pipeline (e.g. an entity whose content is an infinite repetition of
mand mandatory…, similarity 0.86) cannot be removed through the plugin's forget tool.
Suggested fix (plugin side)
In dist/index.js:
- Scoped search fallback: in
searchMemoriesScoped (around L14079+), if a scoped searchMemories returns 0 results, retry the same query without the filters argument against the canonical container, then merge. This restores recall immediately without waiting for the server fix.
- Forget via v4: change
deleteMemory to call DELETE /v4/memories with {id, containerTag} (the documented soft-delete endpoint) instead of DELETE /v3/documents/{id}. Keep the v3 path for document IDs, or detect which endpoint to use.
- Also surfaced during the same investigation (unrelated but adjacent): the installer writes
{autoRecallEveryPrompt: false, captureEveryNTurns: 0} as the fresh-install default (see writeInstallDefaults, cli.js L416-429), which disables mid-session capture for all new users. Consider flipping the default to captureEveryNTurns: 3.
[Bug] Scoped search always returns 0 results (metadata filter silently dropped by /v4/search) +
forgettool 404s on search result IDsSummary
Two closely related bugs in
opencode-supermemory(tested on v2.0.11, OpenCode 1.18.11, Windows):supermemorytool insearchmode withscope: "project"(or"user") always returnscount: 0, even when memories exist and are returned bylistwith the same scope. The root cause is server-side:POST /v4/searchsilently returns zero results when a metadata filter (filters: {AND:[{key:"sm_scope",...}]}) is present, whilePOST /v3/documents/listwith the identical filter works fine.forgettool 404s on IDs returned bysearch— the plugin'sforgetmode callsmemories.delete(id)which maps toDELETE /v3/documents/{id}(a document endpoint), butsearchreturns memory-entity IDs (v4). The two ID spaces are different, so deleting a search result always fails with 404Document not found. Only IDs fromlist(document IDs) can be forgotten.Environment
opencode-supermemory2.0.11opencode-go/deepseek-v4-flashvia custom gatewayrepo_plugin_lab__09b00afed75e0e2d(canonical project container)Repro
Bug 1 — scoped search returns 0
Direct API calls with the real API key (from
~/.supermemory-opencode/credentials.json):Additional probes (all reproduce the 0-result behaviour on
/v4/search):sm_scope=personal→ 0sm_scope=user→ 0type=architecture(different metadata key) → 0filterTypeomitted / changed) → 0Bug 2 — forget 404s on search-result IDs
Root cause confirmed in source (
dist/index.js):searchMemories→client.search.memories(...)→POST /v4/search(returns memory-entity IDs, e.g.mem_*style or opaque IDs)deleteMemory→client.memories.delete(memoryId)→DELETE /v3/documents/{id}(expects a document ID)The correct v4 forget endpoint is
DELETE /v4/memorieswith{id, containerTag}(soft-delete) — the plugin never calls it. Deleting a memory that only exists as a v4 entity (e.g. extracted from a since-deleted document, or a corrupted entity) is therefore impossible through the plugin.Expected behaviour
searchwith ascopeshould return the same memories thatlistwith the same scope shows (either the server should honour metadata filters on/v4/search, or the plugin should fall back to unscoped search and filter client-side).forgetshould accept v4 memory-entity IDs and callDELETE /v4/memories(withcontainerTag), not only v3 document IDs.Impact
getScopeFilters) is effectively broken for everyone — the agent sees "no relevant memories" on every scoped search while memories exist. The unscoped path (searchMemoriesManyover all read containers) works, which is why the bug is easy to miss.mand mandatory…, similarity 0.86) cannot be removed through the plugin'sforgettool.Suggested fix (plugin side)
In
dist/index.js:searchMemoriesScoped(around L14079+), if a scopedsearchMemoriesreturns 0 results, retry the same query without thefiltersargument against the canonical container, then merge. This restores recall immediately without waiting for the server fix.deleteMemoryto callDELETE /v4/memorieswith{id, containerTag}(the documented soft-delete endpoint) instead ofDELETE /v3/documents/{id}. Keep the v3 path for document IDs, or detect which endpoint to use.{autoRecallEveryPrompt: false, captureEveryNTurns: 0}as the fresh-install default (seewriteInstallDefaults,cli.jsL416-429), which disables mid-session capture for all new users. Consider flipping the default tocaptureEveryNTurns: 3.