Documentation

Troubleshooting

A map from symptom to fix for the most common prom.codes issues — MCP, indexer, dashboard, and embeddings.

When something is off, start here. Each section is keyed by what you see, not by what is wrong — so you can jump straight from the log line or the dashboard message to a fix.

MCP server won't connect

A server is missing from /mcp, or claude mcp list shows it as failed.

  1. Run claude mcp list — each server reports a connection status. A failed server points at the real problem.
  2. Inside a session, run /mcp to see live status and the server's stderr. A healthy boot announces its tool list and then waits; any earlier exit is the error.
  3. Re-check the install. The -- separator is required and --env repeats per variable:
    claude mcp add context --env PROMETHEUS_API_KEY=prom_live_… -- npx -y @prom.codes/context-mcp@latest
    
    See Install for Claude Code for the full set.

"Could not locate the bindings file"

The server dies on boot with a better-sqlite3 bindings error (or a tree-sitter native-module error).

context and memory use native modules — better-sqlite3 for the local index, and context also uses tree-sitter plus its language grammars for parsing. Those .node binaries are fetched or compiled by a package install script. If that script is skipped, the binary is missing and the server can't boot. Two situations skip it:

  • npm v12+ (from July 2026): install scripts are opt-in. npm no longer runs preinstall/install/postinstall — including implicit node-gyp native builds — for any dependency unless you explicitly allow it. That is a real supply-chain win (a single compromised transitive package can't run code at install time anymore), but it means our native deps need a one-time approval. Our own three packages ship zero install scripts; only their native dependencies (better-sqlite3, tree-sitter*) have them.
  • ignore-scripts=true in your npm config (older corporate hardening) — same symptom on any npm version.

In a project (a repo with a package.json, or a committed .mcp.json alongside one), review what wants to run and approve the deps you trust:

npm approve-scripts --allow-scripts-pending   # lists the blocked packages
npm approve-scripts                            # approve better-sqlite3, tree-sitter, tree-sitter-*

npm approve-scripts writes the allowlist into package.json — commit it so teammates and CI inherit it — then reinstall.

For a global install (recommended — immune to npx cache issues and faster to start) there is no project package.json to hold the allowlist, so name the packages on the command line and point Claude Code at the built binaries:

npm install -g @prom.codes/context-mcp @prom.codes/memory-mcp @prom.codes/saver \
  --allow-scripts=better-sqlite3,tree-sitter
claude mcp add context --scope user -- node "$(npm root -g)/@prom.codes/context-mcp/dist/bin.js"
claude mcp add memory  --scope user -- node "$(npm root -g)/@prom.codes/memory-mcp/dist/bin.js"
claude mcp add saver   --scope user -- node "$(npm root -g)/@prom.codes/saver/dist/bin.js"

If --allow-scripts-pending also lists tree-sitter-* grammar packages, add them to the comma-list — or set it once for every future install: npm config set allow-scripts=better-sqlite3,tree-sitter --location=user.

The saver has no native dependency; it needs no approval and is in the global command only so one line installs and upgrades all three in lockstep.

Too many node processes / high CPU from prom.codes

Your machine has many @prom.codes/* node processes running — more than the editor windows you have open — and some pin a CPU core.

Each editor window runs its own stdio MCP server, which is normal. The problem is abandoned servers: when an editor's extension host reconnects a server (or ends a session) without closing its stdin, the old process never receives the end-of-input signal it uses to exit. Its file watcher keeps it alive and it keeps re-indexing on every change, so abandoned servers accumulate over days.

Fixed in 0.10.1+: every server now also exits itself after 30 minutes with no MCP traffic (tunable via PROMETHEUS_IDLE_EXIT_MS, 0 disables). An in-use server resets that timer on every request; only truly abandoned ones reap themselves, so they can no longer pile up. Upgrade all three with the one command above, then reconnect.

To clear a backlog that already exists now (older versions don't self-reap), close your editor windows and kill the leftover servers, then reopen:

# macOS / Linux
pkill -f '@prom.codes/(context-mcp|memory-mcp|saver)'
# Windows PowerShell — only prom.codes servers, never other node.exe
Get-CimInstance Win32_Process -Filter "Name='node.exe'" |
  Where-Object { $_.CommandLine -match '@prom\.codes[\\/](context-mcp|memory-mcp|saver)' } |
  ForEach-Object { Stop-Process -Id $_.ProcessId -Force }

The SQLite index is crash-safe (WAL), so killing a server mid-index is safe — it resumes on the next start. The local dashboard lists every running server so you can confirm the count before and after.

Code search is keyword-only / embedding 401

search_code still returns hits, but the result carries "degraded": "lexical+graph-only" and the server logs a 401 from the embedding proxy.

You are using a placeholder or format-only key. The api.prom.codes proxy rejects anything but a real, four-part prom_live_… key with HTTP 401. As of @prom.codes/context-mcp@0.4.3, search_code no longer fails on this — it degrades gracefully to lexical (keyword/BM25) + symbol-graph retrieval, which need no embeddings, and flags the downgrade in its response (degraded, note, vectorError fields). Keyword search and every structural tool (get_file, get_symbol, find_callers, find_callees, find_references, expand_context, framework_overview, list_workspaces) keep working with no key at all.

To restore semantic ranking (the concept-query win), use a real Prometheus key: sign in at app.prom.codes, mint a key at /app/api-keys (it has the shape prom_live_<tag>_<secret>), and set it as PROMETHEUS_API_KEY in the server's env block, then restart the client. The same key unlocks code embeddings and memory across all three servers — embeddings route through the managed api.prom.codes proxy, so you never bring your own provider key.

Once a working key is in place, re-index to backfill the embeddings that were skipped while the key was invalid — ask the agent "reindex this project with force" (the reindex tool clears the snapshot and re-embeds everything; no DB deletion). See Verify your setup & re-indexing.

Server indexes too much / your home folder

The index is huge or seems to crawl outside the repo.

The project is auto-detected on recent versions. As of @prom.codes/context-mcp@0.4.5 the server refuses to auto-index your home directory or a filesystem root, and a later release extends that to a folder that merely contains many projects (e.g. ~/Coding with a dozen repos) — the cases that happen when you open a fresh window or terminal with no single project, so the workspace falls back to the host's working directory. It logs a hint and leaves the index empty instead of crawling everything; call index_status to see the resolved root and why indexing was skipped. A real project or monorepo (anything with a .git, package.json, go.mod, … at its root) is always indexed, however large. To index a real project, open its folder (Claude Code passes it via CLAUDE_PROJECT_DIR) or set PROMETHEUS_WORKSPACE_ROOT to the repo, then restart. To force-index an unconventional root the guard refused, set PROMETHEUS_INDEX_ROOT_OK=1. You should not need to set PROMETHEUS_WORKSPACE_ROOT otherwise — only to point at a different folder than the one you are in.

Vendor / generated trees inflating the index. As of @prom.codes/context-mcp@0.7.0 the indexer honours the repo's own .gitignore (plus a .prometheusignore if you add one, same syntax) on top of the built-in deny-list (node_modules, .next, dist, …). So gitignored folders — vendored clones, large asset dirs like public/cesium/, build output — are skipped automatically. If your index looks bloated (run index_status; a file count far above your real source is the tell), upgrade and run the reindex tool with force once so the already-indexed extra paths are dropped. To index a path your repo gitignores, either add a !negation to .prometheusignore or set PROMETHEUS_RESPECT_GITIGNORE=false (the .prometheusignore file is still honoured). Only the repo-root ignore files are read today.

Scoping what gets indexed — the workspace root is the allowlist. The server only ever walks paths under its resolved workspace root; it never climbs to the parent. So the simplest "index only these folders" control is to point the root at exactly the folder you want — open that project, or set PROMETHEUS_WORKSPACE_ROOT=/path/to/repo. Everything outside is invisible to the indexer by construction. To allowlist a subtree within the root instead, use .prometheusignore with the standard gitignore allowlist idiom — ignore everything, then re-include what you want:

/*
!/.prometheusignore
!/src/

That indexes only src/ and skips the rest, without moving the root.

index_status is also the quickest way to answer "is it installed, which folder, how much is indexed, does my key work?" — it reports the workspace root, index counts, auto-index state, and a zero-cost embedding-key check.

search_code answers but results look generic

The tool responds, but the hits are vague rather than empty.

  • First rule out the 401 case above — a placeholder key drops search to keyword-only (degraded: "lexical+graph-only"), so concept queries rank worse until you add a working embedder.
  • Check the language coverage. The parser supports TS, JS, Python, Go, Rust, Java, and C# today. A repo dominated by an unsupported language indexes few or no symbols.
  • The query may be too short or too generic. The hybrid retriever fuses lexical and semantic signals, but two-token queries still weight heavily on lexical match. Try a full sentence.

POST /index times out

The request hangs for several minutes and then 504s.

The synchronous worker has a 5-minute hard limit. For repos larger than ~5k files, split with the options.include glob and run two indices, or mail us to enable the async mode (POST /index?async=1) on your workspace.

Dashboard says "Tenant not found"

Sign-in succeeds but /app/dashboard redirects to an error.

The signed prom_tenant cookie points to a tenant you no longer belong to (most often because an admin removed you). The dashboard deliberately fails closed instead of silently swapping you back in. Sign out, sign in again, and the resolver falls back to your first remaining membership.

RedirectCauseFix
?invite=expiredToken older than 7 daysAsk the admin to re-invite.
?invite=already_usedInvite was already acceptedSign in normally and switch tenants.
?invite=revokedAdmin revoked the inviteAsk for a fresh one.
?invite=email_mismatchSigned-in email differsSign out, sign in with the invited address.
?invite=invalidToken malformedRe-copy the link from the email; do not edit it.

The /invite/{token} route is documented in detail under Members & invitations.

Audit CSV export is empty

Click Export and download a CSV with just the header row.

That is the contract — the export reflects the current filter. Clear the filters (action, status, date range) and re-export, or widen the date range. RLS guarantees you only ever see your own tenant's rows, so an empty export on the widest filter genuinely means no activity.

429 Too Many Requests

You hit the per-tenant rate limit. The response carries Retry-After and X-RateLimit-Remaining headers — see Rate limits for the actual budgets and the recommended backoff strategy.

Indexer claims an embedder failure

Response includes EMBED_FAILED or 503 after a long delay.

The default embedding provider is occasionally degraded. The worker has a per-tenant circuit breaker that trips after consecutive failures and recovers after 60 s. Just retry. If you see this for more than ~5 minutes, mail info@e-networkers.de — it is almost certainly already on our status feed but a direct ping helps us prioritise.

Still stuck?

Mail info@e-networkers.de with:

  • Your tenant slug (visible top-left in the dashboard).
  • The HTTP status / error code, if any.
  • A request id from the worker response or the audit row.
  • A timestamp in UTC.

That is enough for us to walk our side of the trace. We do not need — and explicitly do not want — your API key or any source code in the report.