Summary
Running any akm search/curate verb from inside a sandboxed agent session (Codex --sandbox read-only, and any comparable sandbox that blocks LAN egress and mounts the FS read-only) produces two streams of unactionable stderr noise and silently degrades results from semantic search to FTS keyword matching. The degraded results are materially wrong, and nothing in the JSON output indicates the degradation happened.
This is increasingly the default way akm gets invoked — the Claude/OpenCode plugins and any agent-driven loop call it from inside a sandbox — so the failure mode is common rather than exotic.
Reproduction
Reproduces 100% on this machine, byte-for-byte identical to what a user reported from an agent session:
codex sandbox -- akm curate "coordinate multi-agent implementation across three repositories with architecture decision gates independent code review and verification"
Vector search failed, skipping: Was there a typo in the url or port?
Vector search failed, skipping: Was there a typo in the url or port?
Vector search failed, skipping: Was there a typo in the url or port?
Vector search failed, skipping: Was there a typo in the url or port?
Vector search failed, skipping: Was there a typo in the url or port?
Vector search failed, skipping: Was there a typo in the url or port?
Vector search failed, skipping: Was there a typo in the url or port?
akm: appendEvent failed: Error: EROFS: read-only file system, open '/home/founder3/.local/share/akm/maintenance.barrier.lock'
The identical command outside the sandbox is completely clean — no warnings, no EROFS.
Root cause
Both messages are the sandbox, not a misconfiguration:
- Network egress is blocked, so
embed() (src/llm/embedder.ts:112) cannot reach the embedding endpoint. vectorScores() catches it at src/indexer/search/db-search.ts:888 and warns.
- The filesystem is read-only, so
appendEvent() (src/core/events.ts:275) cannot create the maintenance-barrier lockfile (src/core/paths.ts:272) that opening the state DB acquires.
Critically, the configuration is fine. Verified from an unsandboxed shell on the same machine:
$ curl -s -w '\nHTTP:%{http_code}\n' http://192.168.0.205:1234/v1/embeddings \
-H 'Content-Type: application/json' \
-d '{"model":"text-embedding-nomic-embed-text-v1.5@q8_0","input":"hello"}'
# → HTTP:200, valid 768-dim embedding returned; model is loaded
$ ls -ld ~/.local/share/akm # writable, ext4 rw,noatime
So "Was there a typo in the url or port?" — Bun's connect-failure string, surfaced verbatim — actively sends the reader to check a URL that is correct. That message costs real debugging time; it did here.
The actual harm: silent result degradation
The noise is annoying. The result quality collapse is the bug. Same query, same machine, same moment:
Unsandboxed (semantic search):
extracted-c19c2368//skills/autonomous-loops
agent-stash//agents/development/agentic-systems-architect
knowledge/wave-based-agent-coordination-patterns
Sandboxed (FTS fallback):
extracted-c19c2368//skills/autonomous-loops
extracted-c7403802//skills/platform-magento/magento-multi-store
extracted-c7403802//skills/catalog-inventory/multi-warehouse
extracted-c7403802//skills/payments-checkout/multi-currency
Three of the four sandboxed results are Magento e-commerce skills that match only on the literal token "multi". For a query about multi-agent coordination, that is noise crowding out the two genuinely relevant assets that semantic search found.
The JSON output carries no indication this happened. summary reads "Selected 4 curated results" with the same confident reason strings ("Strong specialized agent prompt match for…") as a healthy run. An agent consuming this — which is the whole point of --shape agent — cannot tell it is being handed keyword noise, and will act on it.
Three distinct defects
- The warning does not name the endpoint and repeats 7× per invocation. It should state the URL it failed to reach and appear once, e.g.
Vector search unavailable: cannot reach embedding endpoint http://…:1234/v1/embeddings (connection refused) — falling back to keyword search.
- Degradation is invisible to machine consumers. The result payload should carry a flag (
degraded: true / searchMode: "fts-fallback", or an entry in the existing warnings field) so an agent can weigh the results accordingly or tell the user.
- A read-only verb takes a write barrier.
curate is a read operation, yet it acquires the maintenance barrier to append a usage event and hard-errors on a read-only FS. Confirmed this is usage tracking: --no-track-usage suppresses the EROFS entirely (the vector warnings remain). Under a read-only FS this should degrade silently rather than printing a raw Node error with a stack-ish prefix.
Suggested fixes
- Detect the connect-failure class in
vectorScores() and emit one enriched, endpoint-naming warning per invocation instead of one per call site.
- Thread a degradation signal into the curate/search result shape so
--shape agent consumers can see it.
- Make
appendEvent() treat EROFS/EACCES as an expected no-op — best-effort telemetry should not report failure when the environment is legitimately read-only. It already declares itself best-effort; it just is not quiet about this case.
- Consider a broader read-only-environment detection: if the data dir is not writable, skip usage tracking wholesale rather than failing per-write.
Workaround for users hitting this now
akm curate "…" --no-track-usage removes the EROFS line. There is no workaround for the vector-search degradation inside a sandbox short of granting network egress — which is worth documenting, since the results are quietly worse rather than absent.
Environment
- akm 0.9.1
- Linux, ext4
rw,noatime; ~/.local/share/akm writable
- Embedding: lmstudio,
http://192.168.0.205:1234/v1/embeddings, text-embedding-nomic-embed-text-v1.5@q8_0, dim 768 — verified reachable and returning 200 from an unsandboxed shell
akm info: semanticSearch: mode auto, status ready-vec, hasEmbeddings: true, vecAvailable: true, 23510 indexed entries
- Sandbox used for reproduction:
codex sandbox (Codex CLI 0.147.0)
Summary
Running any
akmsearch/curate verb from inside a sandboxed agent session (Codex--sandbox read-only, and any comparable sandbox that blocks LAN egress and mounts the FS read-only) produces two streams of unactionable stderr noise and silently degrades results from semantic search to FTS keyword matching. The degraded results are materially wrong, and nothing in the JSON output indicates the degradation happened.This is increasingly the default way
akmgets invoked — the Claude/OpenCode plugins and any agent-driven loop call it from inside a sandbox — so the failure mode is common rather than exotic.Reproduction
Reproduces 100% on this machine, byte-for-byte identical to what a user reported from an agent session:
codex sandbox -- akm curate "coordinate multi-agent implementation across three repositories with architecture decision gates independent code review and verification"The identical command outside the sandbox is completely clean — no warnings, no EROFS.
Root cause
Both messages are the sandbox, not a misconfiguration:
embed()(src/llm/embedder.ts:112) cannot reach the embedding endpoint.vectorScores()catches it atsrc/indexer/search/db-search.ts:888and warns.appendEvent()(src/core/events.ts:275) cannot create the maintenance-barrier lockfile (src/core/paths.ts:272) that opening the state DB acquires.Critically, the configuration is fine. Verified from an unsandboxed shell on the same machine:
So "Was there a typo in the url or port?" — Bun's connect-failure string, surfaced verbatim — actively sends the reader to check a URL that is correct. That message costs real debugging time; it did here.
The actual harm: silent result degradation
The noise is annoying. The result quality collapse is the bug. Same query, same machine, same moment:
Unsandboxed (semantic search):
Sandboxed (FTS fallback):
Three of the four sandboxed results are Magento e-commerce skills that match only on the literal token "multi". For a query about multi-agent coordination, that is noise crowding out the two genuinely relevant assets that semantic search found.
The JSON output carries no indication this happened.
summaryreads "Selected 4 curated results" with the same confidentreasonstrings ("Strong specialized agent prompt match for…") as a healthy run. An agent consuming this — which is the whole point of--shape agent— cannot tell it is being handed keyword noise, and will act on it.Three distinct defects
Vector search unavailable: cannot reach embedding endpoint http://…:1234/v1/embeddings (connection refused) — falling back to keyword search.degraded: true/searchMode: "fts-fallback", or an entry in the existingwarningsfield) so an agent can weigh the results accordingly or tell the user.curateis a read operation, yet it acquires the maintenance barrier to append a usage event and hard-errors on a read-only FS. Confirmed this is usage tracking:--no-track-usagesuppresses the EROFS entirely (the vector warnings remain). Under a read-only FS this should degrade silently rather than printing a raw Node error with a stack-ish prefix.Suggested fixes
vectorScores()and emit one enriched, endpoint-naming warning per invocation instead of one per call site.--shape agentconsumers can see it.appendEvent()treatEROFS/EACCESas an expected no-op — best-effort telemetry should not report failure when the environment is legitimately read-only. It already declares itself best-effort; it just is not quiet about this case.Workaround for users hitting this now
akm curate "…" --no-track-usageremoves the EROFS line. There is no workaround for the vector-search degradation inside a sandbox short of granting network egress — which is worth documenting, since the results are quietly worse rather than absent.Environment
rw,noatime;~/.local/share/akmwritablehttp://192.168.0.205:1234/v1/embeddings,text-embedding-nomic-embed-text-v1.5@q8_0, dim 768 — verified reachable and returning 200 from an unsandboxed shellakm info:semanticSearch: mode auto, status ready-vec,hasEmbeddings: true,vecAvailable: true, 23510 indexed entriescodex sandbox(Codex CLI 0.147.0)