langchain-ai/deepagents · error · RuntimeError
MCP token file {path} is not a JSON object (found {type(data
Error message
MCP token file {path} is not a JSON object (found {type(data).__name__}). Delete it and run `/mcp login {self._server_name}` in the TUI (or `dcode mcp login {self._server_name}`). What it means
After JSON parsing succeeds, _read verifies the document is a JSON object; null, arrays, or bare scalars would otherwise cause AttributeError later. The file exists and parses but has the wrong shape, so it is treated as corrupt and a RuntimeError is raised with re-login instructions. The message deliberately prints only the type, never the value, because the file content is attacker-controlled.
Source
Thrown at libs/code/deepagents_code/mcp_auth.py:723
f"Failed to read MCP token file {path}: {exc}. "
f"Delete the file and run `/mcp login {self._server_name}` "
f"in the TUI (or `dcode mcp login {self._server_name}`)."
)
raise RuntimeError(msg) from exc
# `json.loads` yields a `dict` only for object literals; `null`, a list,
# or a bare scalar would make the `.get` below raise `AttributeError`,
# which callers do not catch. Fail as a normal corrupt-file error.
if not isinstance(data, dict):
msg = (
f"MCP token file {path} is not a JSON object (found "
f"{type(data).__name__}). Delete it and run "
f"`/mcp login {self._server_name}` in the TUI (or "
f"`dcode mcp login {self._server_name}`)."
)
# Not `TypeError` (TRY004): this is a corrupt-file report, not a
# caller type error, and callers catch the same `RuntimeError` the
# other corruption modes raise. `TypeError` would escape them.
raise RuntimeError(msg) # noqa: TRY004
if data.get("version") != _STORAGE_VERSION:
# Render only the value's type, never the value itself: callers
# print this message verbatim (e.g. `mcp login` list on stderr),
# and the version field is attacker-controlled file content that
# could carry credential material planted by a malformed write.
msg = (
f"MCP token file {path} has unsupported version "
f"({type(data.get('version')).__name__}; expected "
f"{_STORAGE_VERSION!r}). Delete it and run "
f"`/mcp login {self._server_name}` in the "
f"TUI (or `dcode mcp login {self._server_name}`)."
)
raise RuntimeError(msg)
return data
def _write(self, data: dict) -> None:
path = self.path
path.parent.mkdir(parents=True, exist_ok=True)View on GitHub (pinned to a1af029e6e)
Solutions
- Delete the offending token file shown in the message.
- Re-authenticate via `/mcp login <server>` (TUI) or `dcode mcp login <server>`.
- If a tooling script writes this file, fix it to emit a JSON object with the expected schema/version fields.
Example fix
// before $ cat github.json null // after $ rm github.json && dcode mcp login github
Defensive patterns
Strategy: validation
Validate before calling
import json
from pathlib import Path
p = Path(token_store_dir()) / f"{server_name}.json"
if p.exists():
data = json.loads(p.read_text(encoding="utf-8"))
if not isinstance(data, dict):
p.unlink()
run_login(server_name) Type guard
def is_token_dict(data: object) -> TypeGuard[dict]:
return isinstance(data, dict) Try / catch
try:
tokens = store.get_tokens_sync()
except RuntimeError as e:
if "is not a JSON object" in str(e):
store.path.unlink(missing_ok=True)
reauthenticate(server_name)
else:
raise Prevention
- Treat token files as opaque library-owned state - never rewrite them with ad-hoc scripts.
- If scripting token provisioning, always emit a JSON object matching the library's schema.
- Validate any externally provisioned token file with json.loads + isinstance(data, dict) first.
When it happens
Trigger: Any of the _read-backed getters/setters encountering a token file whose top-level JSON value is not an object (e.g. `null`, `[]`, `"str"`, `123`).
Common situations: Someone ran `echo null > token.json` while debugging, a truncating editor emptied then saved `null`, or a script overwrote the file with a JSON array of tokens instead of the expected object schema.
Understand the failure class
Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.
Related errors
- Failed to read MCP token file {path}: {exc}. Delete the file
- Invalid MCP config at {mcp_config_path}: {exc}
- hooks trust store projects must be an object: {path}
- hooks trust store must be a JSON object: {path}
- MCP token file {path} has unsupported version ({type(data.ge
AI-assisted analysis of langchain-ai/deepagents@a1af029e6e (2026-08-29).
Data as JSON: /api/errors/9f1dceb607cd7000.
Report an issue: GitHub.