bytedance/deer-flow · warning · HTTPException

checkpoint must be an object

Error message

checkpoint must be an object

What it means

HTTP 400 raised when a run payload includes a `checkpoint` object that is not a JSON object/Mapping (e.g. a string, list, or number). The checkpoint field lets clients point a run at a prior checkpoint; its shape is validated before any checkpoint ids are extracted.

Source

Thrown at backend/app/gateway/services.py:944

    )


async def apply_checkpoint_to_run_config(
    config: dict[str, Any],
    *,
    body: Any,
    thread_id: str,
    request: Request,
) -> None:
    """Validate an optional run checkpoint and attach it to RunnableConfig."""
    checkpoint = getattr(body, "checkpoint", None)
    checkpoint_id = getattr(body, "checkpoint_id", None)
    checkpoint_ns = ""
    checkpoint_map = None

    if checkpoint:
        if not isinstance(checkpoint, Mapping):
            raise HTTPException(status_code=400, detail="checkpoint must be an object")
        checkpoint_thread_id = checkpoint.get("thread_id")
        if checkpoint_thread_id is not None and str(checkpoint_thread_id) != thread_id:
            raise HTTPException(status_code=400, detail="checkpoint thread_id does not match request thread_id")
        raw_checkpoint_id = checkpoint.get("checkpoint_id")
        if raw_checkpoint_id:
            checkpoint_id = str(raw_checkpoint_id)
        raw_checkpoint_ns = checkpoint.get("checkpoint_ns")
        if raw_checkpoint_ns is not None:
            checkpoint_ns = str(raw_checkpoint_ns)
        checkpoint_map = checkpoint.get("checkpoint_map")

    if not checkpoint_id:
        return

    read_config: dict[str, Any] = {
        "configurable": {
            "thread_id": thread_id,
            "checkpoint_ns": checkpoint_ns,

View on GitHub (pinned to 1dd6ba1acb)

Solutions

  1. Send checkpoint as an object: {"checkpoint_id": "...", "thread_id": "..."} (or omit it and use the top-level checkpoint_id field).
  2. If you only have an id, use the top-level checkpoint_id field rather than the checkpoint object.

Example fix

# before
{"checkpoint": "1ef4f797-8335-6428-8001-8a1506f3b775", "input": {...}}

# after
{"checkpoint_id": "1ef4f797-8335-6428-8001-8a1506f3b775", "input": {...}}
Defensive patterns

Strategy: type-guard

Validate before calling

if ('checkpoint' in payload && (typeof payload.checkpoint !== 'object' || payload.checkpoint === null || Array.isArray(payload.checkpoint))) {
  throw new TypeError('checkpoint must be an object like {checkpoint_id: "..."}');
}

Type guard

const isCheckpointObject = (c: unknown): c is Record<string, unknown> =>
  typeof c === 'object' && c !== null && !Array.isArray(c);

Prevention

When it happens

Trigger: POSTing a run with "checkpoint": "<checkpoint-id-string>" instead of {"checkpoint_id": ...}, or checkpoint: [...] / checkpoint: 123.

Common situations: Clients assuming checkpoint is a plain id string (a common API design); passing the stringified JSON of a checkpoint; copy-paste from a different tool's API.

Related errors


AI-assisted analysis of bytedance/deer-flow@1dd6ba1acb (2026-08-14). Data as JSON: /api/errors/f75bbaeb675c2219. Report an issue: GitHub.