langchain-ai/deepagents · error · RuntimeError

Credential file {path} is not a JSON object. Delete it and r

Error message

Credential file {path} is not a JSON object. Delete it and re-add credentials via /auth.

What it means

Raised by `_read_raw` in auth_store.py when the credential file parses as valid JSON but is not a JSON object (dict) — e.g. a JSON array, string, number, or null at the top level. The library intentionally raises `RuntimeError` (not `TypeError`) so every corruption path surfaces the same error class and one uniform remediation hint to callers.

Source

Thrown at libs/code/deepagents_code/auth_store.py:198

    except (UnicodeDecodeError, json.JSONDecodeError) as exc:
        # `UnicodeDecodeError` (a `ValueError`, not an `OSError`) escapes the
        # handler above when the file holds non-UTF-8 bytes; treat a decode
        # failure as corruption so callers get the same `RuntimeError` hint
        # instead of an unhandled traceback.
        msg = (
            f"Failed to parse credential file {path}: {exc}. "
            "Delete the file and re-add credentials via /auth if it is corrupt."
        )
        raise RuntimeError(msg) from exc
    if not isinstance(data, dict):
        msg = (
            f"Credential file {path} is not a JSON object. "
            "Delete it and re-add credentials via /auth."
        )
        # `RuntimeError` (not `TypeError`) is intentional: every corruption
        # path here surfaces the same error class so callers can render one
        # remediation hint regardless of the specific shape problem.
        raise RuntimeError(msg)  # noqa: TRY004
    version = data.get("version")
    if version != _STORAGE_VERSION:
        msg = (
            f"Credential file {path} has unsupported version {version!r} "
            f"(expected {_STORAGE_VERSION}). Delete it and re-add credentials via "
            "/auth."
        )
        raise RuntimeError(msg)
    return data


def _write_raw(data: dict) -> tuple[str, ...]:
    """Atomically write `data` as the new auth file with 0600 perms.

    Mirrors `mcp_auth.FileTokenStorage._write` so the security posture is
    consistent across both stores. If you change this, update
    `mcp_auth.FileTokenStorage._write` too — they share threat model.

View on GitHub (pinned to a1af029e6e)

Solutions

  1. Delete the credential file at auth_path() and re-add credentials via /auth (set_stored_key).
  2. If the top-level value is a JSON array of credentials, manually convert it to the expected {"version": N, "credentials": {...}} object shape before retrying.
  3. Back up the file before deleting if any entries are hard to reproduce.

Example fix

// before: file contains [] (not an object)
// after: reset the store
pathlib.Path(auth_path()).unlink(missing_ok=True)
set_stored_key("anthropic", key)
Defensive patterns

Strategy: type-guard

Validate before calling

// pre-check top-level shape before calling the API
def _cred_file_shape_ok() -> bool:
    p = pathlib.Path(auth_path())
    if not p.exists():
        return True
    try:
        data = json.loads(p.read_text())
    except (json.JSONDecodeError, OSError):
        return False
    return isinstance(data, dict)

Type guard

def _is_cred_object(data: object) -> TypeGuard[dict[str, object]]:
    return isinstance(data, dict)

Try / catch

try:
    creds = load_credentials()
except RuntimeError as exc:
    if "not a JSON object" in str(exc):
        pathlib.Path(auth_path()).unlink(missing_ok=True)
        creds = {}
    else:
        raise

Prevention

When it happens

Trigger: Calling load_credentials(), set_stored_key(), or delete_stored_key() when the credential file contains valid JSON whose top level is not an object, such as `[]`, `"text"`, `123`, or `null`.

Common situations: The file was overwritten by another process writing a JSON array/list of credentials; a user 'cleaned up' the file leaving an empty JSON value; a migration tool wrote an incompatible schema.

Related errors


AI-assisted analysis of langchain-ai/deepagents@a1af029e6e (2026-08-29). Data as JSON: /api/errors/451d2bb175d84ab1. Report an issue: GitHub.