bytedance/deer-flow · warning · HTTPException

checkpoint thread_id does not match request thread_id

Error message

checkpoint thread_id does not match request thread_id

What it means

HTTP 400 raised when the checkpoint object's thread_id differs from the thread_id in the request URL/body. Since checkpoints belong to exactly one thread, a mismatch means the client is pointing a run at another thread's checkpoint; the gateway refuses rather than cross-read state.

Source

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

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,
            "checkpoint_id": str(checkpoint_id),
        }
    }

View on GitHub (pinned to 1dd6ba1acb)

Solutions

  1. Drop the thread_id key from the checkpoint object (it is optional), or set it to the same thread as the request.
  2. Fetch the checkpoint list for the target thread and use checkpoints from there only.

Example fix

# before
POST /threads/t2/runs  body: {"checkpoint": {"thread_id": "t1", "checkpoint_id": "cp1"}, ...}

# after
POST /threads/t2/runs  body: {"checkpoint": {"thread_id": "t2", "checkpoint_id": "cp1"}, ...}
Defensive patterns

Strategy: validation

Validate before calling

if (payload.checkpoint?.thread_id != null && payload.checkpoint.thread_id !== tid) {
  delete payload.checkpoint.thread_id; // or fail fast client-side
}

Prevention

When it happens

Trigger: POST /threads/{thread_id}/runs with a checkpoint dict whose "thread_id" key names a different thread.

Common situations: Client-side thread switching that reuses a cached checkpoint object from a previous thread; copy-pasting an example payload from another thread; ids confused between UI conversations.

Related errors


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