{"record":{"id":"7e8a93e57396c3f3","repo":"langchain-ai/deepagents","slug":"langgraph-returned-non-object-thread-state","errorCode":null,"errorMessage":"LangGraph returned non-object thread state.","messagePattern":"LangGraph returned non-object thread state\\.","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"libs/code/deepagents_code/offload_api.py","lineNumber":552,"sourceCode":"        {str(key): value for key, value in responses.items()},\n    )\n\n\ndef _hydrate_state(values: object) -> _OffloadState:\n    \"\"\"Hydrate serialized checkpoint messages for the compaction service.\n\n    Args:\n        values: State values returned by LangGraph Server.\n\n    Returns:\n        A shallow state copy containing LangChain message objects.\n\n    Raises:\n        TypeError: If the server returns an unexpected state shape.\n    \"\"\"\n    if not isinstance(values, dict):\n        msg = \"LangGraph returned non-object thread state.\"\n        raise TypeError(msg)\n    state = dict(values)\n    messages = state.get(\"messages\", [])\n    if not isinstance(messages, list):\n        msg = \"LangGraph returned a non-list messages channel.\"\n        raise TypeError(msg)\n    state[\"messages\"] = convert_to_messages(messages)\n\n    # LangGraph serializes the summary stored inside the private event channel\n    # independently of the top-level `messages` channel. The summarization SDK\n    # prepends it to the effective conversation, so it must be a message object\n    # too rather than the serialized dict returned by the thread API.\n    event = state.get(\"_summarization_event\")\n    if isinstance(event, Mapping) and \"summary_message\" in event:\n        hydrated_event = dict(event)\n        summary_message = hydrated_event[\"summary_message\"]\n        hydrated_event[\"summary_message\"] = convert_to_messages([summary_message])[0]\n        state[\"_summarization_event\"] = hydrated_event\n    return cast(\"_OffloadState\", state)","sourceCodeStart":534,"sourceCodeEnd":570,"githubUrl":"https://github.com/langchain-ai/deepagents/blob/a1af029e6e73cb17c36bff823d227747b28e91e1/libs/code/deepagents_code/offload_api.py#L534-L570","documentation":"After fetching thread state, the SDK expects LangGraph's `get_state` values to be an object (dict). If the server returns any other shape — null, a list, or a scalar — _hydrate_state raises this TypeError rather than crashing later with an opaque attribute error. This usually signals a server/runtime mismatch or corrupted thread state rather than a problem with your request.","triggerScenarios":"_execute_offload calling client.threads.get_state(thread_id) and receiving values that is not a dict (None from an empty/unknown thread, a list, or a differently shaped payload from an incompatible server version).","commonSituations":"Pointing the client at an older/incompatible LangGraph thread server whose state schema differs, a thread id that exists but has no object-shaped state, proxy/gateway mangling the response body, or a mocked client in tests returning a non-dict.","solutions":["Verify the thread server version matches the SDK's expected LangGraph threads API; upgrade the server or pin the SDK accordingly.","Confirm the thread_id exists (client.threads.get(thread_id)) before offloading; recreate the thread if its state is missing.","Catch TypeError around the offload call and surface 'unreadable thread state' to the user instead of retrying blindly.","Inspect the raw get_state response (log it) to see what shape is actually returned; check for proxies rewriting the body."],"exampleFix":"// before\nstate = await offload(thread_id, payload)\n// after\ntry:\n    state = await offload(thread_id, payload)\nexcept TypeError as exc:\n    if \"non-object thread state\" in str(exc):\n        raise RuntimeError(f\"Thread {thread_id} state is unreadable; recreate the thread\") from exc\n    raise","handlingStrategy":"try-catch","validationCode":"before = await client.threads.get_state(thread_id)\nif not isinstance(before, dict):\n    raise RuntimeError(f\"Thread {thread_id} returned non-object state; server/schema mismatch\")","typeGuard":"def is_thread_state(values) -> bool:\n    return isinstance(values, dict)","tryCatchPattern":"try:\n    state = await offload(thread_id, payload)\nexcept TypeError as exc:\n    if \"non-object thread state\" in str(exc):\n        raise RuntimeError(\n            f\"Thread {thread_id} state is unreadable; verify server version or recreate the thread\"\n        ) from exc\n    raise","preventionTips":["Pin the thread server and SDK to compatible LangGraph versions","Confirm the thread exists before offloading (client.threads.get)","Log raw get_state responses once when integrating a new server/proxy","Do not retry blindly on this error — it is deterministic, not transient"],"tags":["langgraph","server-response","thread-state","type-error"],"backgroundTag":"unexpected-server-response-shape","analyzedSha":"a1af029e6e73cb17c36bff823d227747b28e91e1","analyzedAt":"2026-08-29T11:43:24.718Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}