langchain-ai/deepagents · error · ValueError

workspace configuration must be JSON serializable

Error message

workspace configuration must be JSON serializable

What it means

`canonical_workspace_config` JSON-serializes the config to produce a canonical fingerprint. This ValueError is raised when the config dict contains values that cannot be JSON-serialized (e.g. sets, datetime objects, custom class instances, non-string dict keys that cannot convert), so no stable fingerprint can be computed.

Source

Thrown at libs/code/deepagents_code/workspace.py:113


def canonical_workspace_config(value: object | None) -> tuple[str, str]:
    """Return bounded canonical JSON and its SHA-256 fingerprint.

    Raises:
        TypeError: If the configuration is not an object.
        ValueError: If it cannot be serialized or exceeds the size limit.
    """
    if value is None:
        value = {}
    if not isinstance(value, dict):
        msg = "workspace_config must be an object"
        raise TypeError(msg)
    try:
        serialized = json.dumps(value, sort_keys=True, separators=(",", ":"))
    except (TypeError, ValueError) as exc:
        msg = "workspace configuration must be JSON serializable"
        raise ValueError(msg) from exc
    if len(serialized) > _MAX_CONFIG_LENGTH:
        msg = "workspace configuration is too large"
        raise ValueError(msg)
    return serialized, hashlib.sha256(serialized.encode()).hexdigest()


def _fingerprint(value: object) -> str:
    serialized = json.dumps(value, sort_keys=True, separators=(",", ":"))
    return hashlib.sha256(serialized.encode()).hexdigest()


def resolve_workspace(
    cwd: object,
    workspace_config: object | None = None,
    *,
    config_fingerprint: str | None = None,
) -> WorkspaceBinding:
    """Resolve and validate a client workspace claim.

View on GitHub (pinned to a1af029e6e)

Solutions

  1. Convert unserializable values to JSON-native types (str for Path/datetime, list for set) before passing
  2. Use `json.dumps(workspace_config)` in a pre-check to find the offending value
  3. Ensure all dict keys are strings

Example fix

// before
cfg = {"deadline": datetime.now(), "roots": {Path("/tmp")}}
// after
cfg = {"deadline": datetime.now().isoformat(), "roots": [str(p) for p in roots]}
Defensive patterns

Strategy: validation

Validate before calling

try:
    json.dumps(workspace_config, sort_keys=True)
except (TypeError, ValueError) as exc:
    raise ValueError(f"workspace_config not JSON serializable: {exc}") from exc

Try / catch

try:
    bind_thread_workspace(tid, cwd, workspace_config=cfg)
except ValueError as exc:
    if "JSON serializable" in str(exc):
        cfg = json.loads(json.dumps(cfg, default=str))
        bind_thread_workspace(tid, cwd, workspace_config=cfg)

Prevention

When it happens

Trigger: Calling `canonical_workspace_config`, `bind_thread_workspace`, `resolve_workspace`, or `require_thread_workspace` with a dict containing unserializable values such as `set()`, `datetime.now()`, path objects, or a key of an unsupported type.

Common situations: Passing `Path` objects or datetimes parsed from CLI args in the config; using sets for allowed paths; dict keys that are ints or tuples; configs built from in-memory objects rather than JSON-loaded data.

Related errors


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