{"record":{"id":"68075b26babdf6b3","repo":"langchain-ai/deepagents","slug":"thread-id-path-parameter-must-be-non-empty","errorCode":null,"errorMessage":"thread_id path parameter must be non-empty.","messagePattern":"thread_id path parameter must be non-empty\\.","errorType":"validation","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"libs/code/deepagents_code/offload_api.py","lineNumber":877,"sourceCode":"    Args:\n        thread_id: LangGraph thread to compact.\n        operation_id: Opaque client-generated attempt identity.\n        context: Runtime model and hooks context.\n        hook_responses: Accumulated hook replies keyed by invocation id.\n\n    Returns:\n        A complete result or a hook request that must be answered.\n\n    Raises:\n        TypeError: If `thread_id` is empty.\n        _OffloadConflictError: If the thread is active or changes before commit.\n        _OffloadUnavailableError: If the server runtime cannot be built, so no\n            operation can run.\n        RuntimeError: If the operation attempts to write conversation messages.\n    \"\"\"\n    if not thread_id:\n        msg = \"thread_id path parameter must be non-empty.\"\n        raise TypeError(msg)\n    client = _thread_client()\n    async with _thread_lock(thread_id):\n        await _require_idle_thread(client, thread_id)\n        before = await client.threads.get_state(thread_id)\n        if before.get(\"next\") or before.get(\"tasks\") or before.get(\"interrupts\"):\n            msg = \"Cannot offload a thread with pending graph work.\"\n            raise _OffloadConflictError(msg)\n\n        state = _hydrate_state(before.get(\"values\"))\n        if not state.get(\"messages\"):\n            # An empty thread is \"nothing to offload\", not a failure. Answer it\n            # here: `_checkpoint_id` below rejects a thread with no checkpoint,\n            # so without this the graceful `empty` branch in\n            # `OffloadOperation.execute` is unreachable over HTTP and the user\n            # is told the operation failed.\n            return {\n                \"status\": \"complete\",\n                \"result\": unchanged_offload_result(\"empty\", messages=0, tokens=0),","sourceCodeStart":859,"sourceCodeEnd":895,"githubUrl":"https://github.com/langchain-ai/deepagents/blob/a1af029e6e73cb17c36bff823d227747b28e91e1/libs/code/deepagents_code/offload_api.py#L859-L895","documentation":"_execute_offload requires the thread_id path parameter to be truthy (a non-empty identifier) before it acquires the thread lock and talks to the thread server. An empty string, None, or other falsy thread_id means the caller never resolved a workspace/thread binding, so the operation cannot be addressed and is rejected with a TypeError.","triggerScenarios":"Calling offload() with thread_id='', thread_id=None, or an unvalidated variable that resolved to empty because no workspace/thread binding was set (see test_missing_workspace_binding_is_rejected / test_missing_workspace_context_is_rejected).","commonSituations":"A fresh session where the workspace binding step was skipped, an env/config key for the thread id missing so the default resolved to '', stripping whitespace in config leaving an empty value, or calling offload before thread creation.","solutions":["Resolve/validate the binding before calling: create or fetch the thread and pass its real id.","Guard the call: if not thread_id: raise a clear configuration error or initialize the workspace first.","Check your config/env for the thread/workspace id — an unset variable often degrades to an empty string rather than None.","Strip and re-check: thread_id = (raw or '').strip() and fail fast if empty."],"exampleFix":"// before\nawait offload(thread_id=os.environ.get(\"THREAD_ID\", \"\"), payload=payload)\n// after\nthread_id = os.environ.get(\"THREAD_ID\", \"\").strip()\nif not thread_id:\n    raise ValueError(\"THREAD_ID is not configured; bind a workspace thread first\")\nawait offload(thread_id=thread_id, payload=payload)","handlingStrategy":"validation","validationCode":"def ensure_thread_id(thread_id):\n    if not thread_id or not isinstance(thread_id, str) or not thread_id.strip():\n        raise ValueError(\"thread_id must be resolved (non-empty) before offload; bind a workspace thread first\")\n    return thread_id.strip()","typeGuard":"def has_thread_id(thread_id) -> bool:\n    return isinstance(thread_id, str) and bool(thread_id.strip())","tryCatchPattern":"try:\n    state = await offload(thread_id, payload)\nexcept TypeError as exc:\n    if \"thread_id path parameter\" in str(exc):\n        raise RuntimeError(\"No thread bound to this session; complete workspace/thread binding first\") from exc\n    raise","preventionTips":["Complete workspace/thread binding before issuing offload operations","Treat unset config as an error, not an empty-string default","Strip and validate thread ids read from env/config at startup","Create or fetch the thread (client.threads.create/get) before calling offload"],"tags":["type-error","validation","thread-id","configuration"],"backgroundTag":"missing-required-field","analyzedSha":"a1af029e6e73cb17c36bff823d227747b28e91e1","analyzedAt":"2026-08-29T11:43:24.718Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}