langchain-ai/deepagents · error · TypeError

workspace_config must be an object

Error message

workspace_config must be an object

What it means

`canonical_workspace_config` normalizes an optional workspace config into a canonical serialized form plus fingerprint. This library raises this TypeError when the caller passes a non-dict, non-None value (e.g. a list, string, or number) as `workspace_config`, because the config must be a JSON object of key/value settings.

Source

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

    if os.name != "nt":
        from deepagents.backends.utils import validate_path

        validate_path(str(resolved))
    return resolved


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,

View on GitHub (pinned to a1af029e6e)

Solutions

  1. Ensure the value passed as `workspace_config` is a `dict` (or omitted/None for defaults)
  2. If loading from a string or file, `json.loads` it first and assert the top level is an object
  3. If your config is a list, wrap or restructure it under an object key

Example fix

// before
resolve_workspace(cwd, workspace_config=["a", "b"])
// after
resolve_workspace(cwd, workspace_config={"allowed_paths": ["a", "b"]})
Defensive patterns

Strategy: type-guard

Validate before calling

if workspace_config is not None and not isinstance(workspace_config, dict):
    raise TypeError("workspace_config must be a dict")

Type guard

def is_workspace_config(v: object) -> TypeGuard[dict[str, Any]]:
    return v is None or isinstance(v, dict)

Try / catch

try:
    resolve_workspace(cwd, workspace_config)
except TypeError as exc:
    logging.error("bad workspace_config type: %s", exc)
    workspace_config = {}

Prevention

When it happens

Trigger: Calling `canonical_workspace_config` directly, or `bind_thread_workspace` / `resolve_workspace` / `require_thread_workspace`, with `workspace_config` set to a JSON array, string, int, or None-wrapped object instead of a dict (e.g. loading config from YAML that yields a list, or passing `workspace_config='{}'` as a JSON string).

Common situations: Config loaded from a YAML file that parses to a list at top level; JSON config passed as a raw string instead of `json.loads`-ed; a caller wrapping the dict in an extra container; refactored code that changed the config shape.

Related errors


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