{"record":{"id":"ad97e27a54b3b8c3","repo":"langchain-ai/deepagents","slug":"thread-id-must-be-non-empty","errorCode":null,"errorMessage":"thread_id must be non-empty","messagePattern":"thread_id must be non-empty","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"libs/code/deepagents_code/workspace.py","lineNumber":302,"sourceCode":"\nasync def bind_thread_workspace(\n    thread_id: str,\n    cwd: object,\n    workspace_config: object | None = None,\n    *,\n    config_fingerprint: str | None = None,\n) -> WorkspaceBinding:\n    \"\"\"Atomically create or verify a thread workspace binding.\n\n    Returns:\n        The immutable binding for the thread.\n\n    Raises:\n        ValueError: If the thread is invalid.\n    \"\"\"\n    if not isinstance(thread_id, str) or not thread_id:\n        msg = \"thread_id must be non-empty\"\n        raise ValueError(msg)\n    proposed = await asyncio.to_thread(\n        resolve_workspace,\n        cwd,\n        workspace_config,\n        config_fingerprint=config_fingerprint,\n    )\n    return await asyncio.to_thread(_bind, thread_id, proposed)\n\n\nasync def get_thread_workspace(thread_id: str) -> WorkspaceBinding | None:\n    \"\"\"Read a thread's durable workspace binding.\n\n    Returns:\n        The binding, or `None` when the thread is unbound.\n    \"\"\"\n    if not isinstance(thread_id, str) or not thread_id:\n        return None\n    return await asyncio.to_thread(_read, thread_id)","sourceCodeStart":284,"sourceCodeEnd":320,"githubUrl":"https://github.com/langchain-ai/deepagents/blob/a1af029e6e73cb17c36bff823d227747b28e91e1/libs/code/deepagents_code/workspace.py#L284-L320","documentation":"`bind_thread_workspace` validates that `thread_id` is a non-empty string before doing any work. This ValueError means the thread identifier was missing, an empty string, or not a string at all.","triggerScenarios":"Calling `bind_thread_workspace(thread_id=None)`, `thread_id=\"\"`, or a non-str value (int, UUID object) without converting to string.","commonSituations":"Thread id not yet generated because session creation failed upstream; passing a UUID object instead of `str(uuid)`; an off-by-one where the variable holding the id was never assigned.","solutions":["Pass a non-empty string thread id; convert UUIDs with `str()`","Ensure the thread/session id is created before binding","Add a pre-call check `assert isinstance(tid, str) and tid`"],"exampleFix":"// before\nbind_thread_workspace(thread_id=session.uuid, cwd=cwd)\n// after\nbind_thread_workspace(thread_id=str(session.uuid), cwd=cwd)","handlingStrategy":"type-guard","validationCode":"if not isinstance(thread_id, str) or not thread_id:\n    raise ValueError(\"thread_id must be a non-empty string\")","typeGuard":"def is_valid_thread_id(v: object) -> TypeGuard[str]:\n    return isinstance(v, str) and bool(v)","tryCatchPattern":"try:\n    await bind_thread_workspace(thread_id, cwd)\nexcept ValueError as exc:\n    if \"thread_id\" in str(exc):\n        thread_id = str(uuid.uuid4())\n        await bind_thread_workspace(thread_id, cwd)","preventionTips":["Convert UUIDs with str() before binding","Generate the thread id before calling bind","Never pass empty strings as ids"],"tags":["workspace","validation","thread-id","argument-error"],"backgroundTag":"missing-or-empty-thread-id","analyzedSha":"a1af029e6e73cb17c36bff823d227747b28e91e1","analyzedAt":"2026-08-29T11:43:24.718Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}