{"record":{"id":"e504753e4b82231b","repo":"langchain-ai/deepagents","slug":"summarizer-returned-a-type-summary-message-nam","errorCode":null,"errorMessage":"Summarizer returned a {type(summary_message).__name__} summary message; expected HumanMessage.","messagePattern":"Summarizer returned a (.+?) summary message; expected HumanMessage\\.","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"libs/code/deepagents_code/offload_middleware.py","lineNumber":1570,"sourceCode":"            TypeError: If the summarizer's first message is not the\n                `HumanMessage` the event schema declares.\n        \"\"\"\n        summary_message = summarization._build_new_messages_with_path(\n            summary, file_path\n        )[0]\n        if not isinstance(summary_message, HumanMessage):\n            # `_build_new_messages_with_path` is annotated `list[AnyMessage]`\n            # but documents (and the SDK's own call site assumes, with a type\n            # suppression) that element 0 is the summary `HumanMessage`. Check\n            # rather than suppress: the node turns this into a visible\n            # \"Compaction failed\" instead of checkpointing an event whose\n            # `summary_message` violates its own schema.\n            msg = (\n                \"Summarizer returned a \"\n                f\"{type(summary_message).__name__} summary message; expected \"\n                \"HumanMessage.\"\n            )\n            raise TypeError(msg)\n        return {\n            \"_summarization_event\": {\n                # Absolute, not relative: a second `/offload` on the same thread\n                # reads this back as its base.\n                \"cutoff_index\": state_cutoff,\n                \"summary_message\": summary_message,\n                \"file_path\": file_path,\n            },\n            \"_summarization_session_id\": session_id,\n        }\n\n\ndef _create_cli_compaction_middleware(\n    model: str | BaseChatModel,\n    backend: BackendProtocol,\n    *,\n    cli_max_retries: int | None = None,\n    summarization_model_spec: str | None = None,","sourceCodeStart":1552,"sourceCodeEnd":1588,"githubUrl":"https://github.com/langchain-ai/deepagents/blob/a1af029e6e73cb17c36bff823d227747b28e91e1/libs/code/deepagents_code/offload_middleware.py#L1552-L1588","documentation":"After forced compaction, the SDK's summarizer is expected to produce a `HumanMessage` as the summary message; the offload event stores this message in the checkpoint. `_forced_compaction_update` raises TypeError if the summarizer returns any other message type, since a schema-violating summary would break later compaction rounds that read the event back as their base.","triggerScenarios":"A custom or upgraded summarization model/prompt whose output is parsed into an AIMessage, SystemMessage, or other message class instead of HumanMessage during `/offload` forced compaction.","commonSituations":"Swapping the summarizer model for one with different response parsing; overriding summarization prompts so the structured summary schema is violated; SDK version changes to SummarizationMiddleware's summary-message construction.","solutions":["Restore/keep dcode's summarizer configuration so the summary is produced as a HumanMessage.","Inspect the summarizer's output parsing; add a coercion step that wraps the summary text in a HumanMessage.","Check for an SDK upgrade that changed summary-message type and align dcode's expectations or pin the SDK."],"exampleFix":"// before\ncutoff, summary = summarizer.summarize(messages)\nreturn build_update(cutoff, summary)  # summary is AIMessage -> TypeError\n// after\nif not isinstance(summary, HumanMessage):\n    summary = HumanMessage(content=summary.content)\nreturn build_update(cutoff, summary)","handlingStrategy":"type-guard","validationCode":"summary_message = summarizer_output.summary_message\nassert isinstance(summary_message, HumanMessage), f\"got {type(summary_message).__name__}\"","typeGuard":"from langchain_core.messages import HumanMessage\n\ndef is_human_summary(msg: object) -> bool:\n    return isinstance(msg, HumanMessage)","tryCatchPattern":"try:\n    result = await offload(thread_id)\nexcept TypeError as e:\n    if \"expected HumanMessage\" in str(e):\n        restore_default_summarizer_config()  # custom model/prompt broke the schema\n    raise","preventionTips":["Keep dcode's default summarizer model and prompt; custom overrides must emit the documented schema.","Add a unit test running the summarizer over a fixture conversation and asserting HumanMessage output.","When upgrading the SDK, diff SummarizationMiddleware's summary-message construction."],"tags":["summarization","type-mismatch","compaction","schema"],"backgroundTag":"unexpected-message-type","analyzedSha":"a1af029e6e73cb17c36bff823d227747b28e91e1","analyzedAt":"2026-08-29T11:43:24.718Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}