Troubleshooting
Most problems come down to a handful of causes, and each one leaves a clear trace. Every entry here is the same shape: what you see, why it happens, and what to do about it.
Start here #
Before anything else, ask the engine how it is. GET /health needs no token
and reports the version, the storage adapter, whether embeddings are working, and how many facts,
sessions and docs it holds. grounded status reads the same thing and adds
how the service was installed.
Every error the API returns carries a stable code next to a plain-language
error message. The codes below are the ones you'll actually meet; the full
mapping is on the HTTP API page.
Your agent can't connect #
- You see: the agent reports it can't reach Grounded, or every call fails with
401UNAUTHORIZED. A startup hook gives no brief at all: hooks are failure-silent by design, so a broken connection looks like an empty start. - Why: one of three things. The base URL points somewhere Core isn't listening. Core was
installed with
--tokenand the agent sends no token, or the wrong one. Or the agent is on another computer: Core only answers on127.0.0.1unless you turn on LAN sharing, which is off by default. - Fix: from the agent's machine,
curl -s <base URL>/health. No answer means the URL is wrong or Core is down: checkgrounded statusand setGROUNDED_URLfor the hooks and commands (defaulthttp://127.0.0.1:7437). If/healthanswers but other calls return401, the token is the problem, because/healthnever asks for one: setGROUNDED_TOKENto the token Core was installed with. From another computer, turn sharing on and pair it; over sharing, host administration (/sharing,/addons/…) answers403LOCAL_ONLY, which is expected.
Recall comes back empty #
- You see: the agent says Grounded is empty, or recall misses docs you know you ingested.
- Why: usually one of these. The agent read the wrong key: results are in
.data, not.results. The docs sit in a lane the query didn't ask for: recall and the brief read only theglobaldoc lane unless you passscopes. Or the agent is talking to a different engine than the one you filled. - Fix: look at
meta.returnedbefore trusting an empty list. Comparecountsin/healthwith what you expect. For docs in another lane, add"scopes": ["global", "<lane>"]; lanes are explained under doc lanes.
Docs ingest reports scanned: 0 #
- You see:
POST /docs/ingestreturns200, and every count is zero,scannedincluded. Nothing new shows up in recall. - Why: the engine reads the files itself, from its own filesystem. It found a folder at that
path, but no
.md,.markdown,.mdxor.txtfiles in it. The usual cause is that the engine is looking at a different folder than you are. A Core running in Docker sees the container's filesystem:/home/you/noteson the host means nothing inside the container unless it is mounted there. A path that doesn't exist for the engine at all, or that it can't read, is refused instead, with400INGEST_PATH_UNREADABLEand the paths listed. - Fix: always check
scanned > 0. Pass absolute paths as the engine sees them:- Docker: mount the folder at the same path it has on the host
(
-v /home/you/notes:/home/you/notes:ro), so one path works on both sides. - Windows: use a Windows path, with forward slashes or doubled backslashes in JSON:
"C:/Users/you/notes"or"C:\\Users\\you\\notes". A Git Bash path like/c/Users/…or a WSL path like/mnt/c/…only works for an engine running in that environment. - Permissions: the service runs as the user it was installed for. A folder only another account (or root) can read is invisible to it.
"dryRun": trueshows what an ingest would do without writing anything. The/grounded-ingestcommand makes the check for you. - Docker: mount the folder at the same path it has on the host
(
Writes fail with EMBED_ERROR #
- You see: adding a fact or session, ingesting docs, or recall answers
503withEMBED_ERROR, often saying the Ollama request failed. Search by meaning has stopped working. - Why: Core is configured to embed with a provider that isn't answering, most often Ollama
that has stopped or moved. While embeddings are on, every write and every recall needs it.
/healthshows the provider and whether it isok. - Fix: start the provider again, and everything resumes. If you'd rather run without it, set
the provider to
nonein~/.grounded/config.tomland restart: recall then matches on keywords, and writes need no model. To search by meaning without Ollama, use the Embeddings add-on, which runs a small model inside Core.
A quick stopgap for one recall: "lexicalOnly": true skips
the provider for that query. POST /impact never uses it, so dependency checks
keep working throughout.
The service won't start #
- You see:
grounded statussays it isn't running, the console doesn't load, or Companion never reaches ready. - Why: the log says. Most often port
7437is already taken, by another program or by a second copy of Core. Otherwise it is a mistake inconfig.tomlor, on the Postgres adapter, a database it can't reach. - Fix: read
grounded logs(on Windows the file is%USERPROFILE%\.grounded\logs\grounded.log). If the port is taken, stop whatever holds it, or move Core:grounded uninstall(your data stays), thengrounded install --port <n>. A self-hosted service takesGROUNDED_API_PORTinstead; see environment. Then point agents at the new port withGROUNDED_URL. LAN sharing uses the next port up, so leave that one free too.
Windows: the grounded command fails #
- You see: any
groundedcommand on Windows fails straight away, with Node saying it cannot find a module whose path ends in..libcli.mjs. - Why: a bug in the 0.2.0 Windows launcher,
grounded.cmd: it lost the backslashes in its own path. Core itself is fine and keeps running. Fixed in the next release. - Fix: use Companion, which does the same jobs
without the command. Or call the CLI with Node directly, passing the same arguments:
node "%USERPROFILE%\.grounded\lib\current\lib\cli.mjs" status. Older installs keep it in%USERPROFILE%\Grounded\.core\lib\current\lib\cli.mjs. Ifwhere nodefinds nothing, use the Node that Companion installed, in%USERPROFILE%\.grounded\runtime\.
MCP tools don't show up #
- You see: the harness lists no
ground_*tools, or reports that thegroundedMCP server failed to start. - Why: on 0.2.0 the
grounded-mcpcommand thatgrounded mcp installprints is not on the PATH of a release install. MCP also only runs on the computer that holds the cabinet. - Fix: point the harness at the bundled server with Node, as shown under agent setup: MCP. On another computer, skip MCP and use the HTTP API: nothing in Grounded needs MCP.
A call is refused with 400 #
- You see:
400VALIDATION_ERRORon a call that looks right. - Why: Grounded refuses rather than guessing. The message names the reason: a field the route
doesn't accept (it lists the ones it does), a
limitoutside1..200on recall and impact, an unknowntimezone, or a fact, session summary or vision longer than its share of the brief. - Fix: do what the message says: rename or drop the field, page with
offseton the list routes instead of a huge limit, or shorten the text. A write over its cap is told how much to trim.
Your engine is older than these docs #
- You see: a route, field or command from these docs that your Core doesn't know: a
404, an unknown-field400, or a missing option. - Why: the site documents the latest release. An engine installed earlier stays on its version until you update it.
- Fix: compare
versionfromGET /healthwith "Latest Core" in getgrounded.dev/llms.txt. If yours is older, update: from Companion's Settings on Windows and macOS, or re-runinstall.shandgrounded restarton Linux. Your data is never touched. See updating. Your engine's ownGET /llms.txtalways describes exactly what it supports.