{"record":{"id":"fe45545964e86adf","repo":"langchain-ai/deepagents","slug":"unsupported-hook-specific-output-type-specific","errorCode":null,"errorMessage":"Unsupported hook-specific output: {type(specific).__name__}","messagePattern":"Unsupported hook-specific output: (.+?)","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"libs/code/deepagents_code/hooks/reducer.py","lineNumber":298,"sourceCode":"                    f\"Ignored Stop continuation after {MAX_STOP_CONTINUATIONS} \"\n                    \"consecutive attempts\"\n                ),\n            )\n        )\n        return\n    state.continue_loop = True\n    state.feedback.append(message)\n\n\n@singledispatch\ndef _merge_specific(\n    specific: HookSpecificOutput,\n    _invocation: HookInvocation,\n    _state: _Reduction,\n    _handler_id: str,\n) -> None:\n    msg = f\"Unsupported hook-specific output: {type(specific).__name__}\"\n    raise TypeError(msg)\n\n\n@_merge_specific.register\ndef _merge_session_start(\n    specific: SessionStartSpecificOutput,\n    _invocation: HookInvocation,\n    state: _Reduction,\n    handler_id: str,\n) -> None:\n    _append(state.context, specific.additional_context)\n    for attr, wire_name in _UNSUPPORTED_SESSION_START_FIELDS:\n        value = getattr(specific, attr)\n        if value not in (None, False, [], \"\"):\n            _diagnose_unsupported_field(state, handler_id, wire_name)\n\n\n@_merge_specific.register\ndef _merge_user_prompt_submit(","sourceCodeStart":280,"sourceCodeEnd":316,"githubUrl":"https://github.com/langchain-ai/deepagents/blob/a1af029e6e73cb17c36bff823d227747b28e91e1/libs/code/deepagents_code/hooks/reducer.py#L280-L316","documentation":"`_merge_specific` is a singledispatch function in `libs/code/deepagents_code/hooks/reducer.py` that folds handler-specific output (e.g. session-start context, decision fields) into the reduction state. The fallback raises `TypeError` when handed a `HookSpecificOutput` subtype with no registered merger, indicating output that the reducer cannot incorporate.","triggerScenarios":"A hook handler returns a `HookSpecificOutput` subclass that has no `@_merge_specific.register` handler — typically a custom output type, a mocked output in tests, or output from a newer library version not matched by the reducer table.","commonSituations":"Writing a custom hook handler that returns a hand-rolled HookSpecificOutput subclass; test doubles implementing the output protocol; version skew between hook handler code and the reducer.","solutions":["Return a supported HookSpecificOutput type (e.g. `SessionStartSpecificOutput`) from the handler","Register a merger via `@_merge_specific.register` for the custom output type","Update/align library versions so handler outputs and reducer registrations match"],"exampleFix":"// before\nclass MyOutput(HookSpecificOutput): ...\nreturn MyOutput()\n// after\nreturn SessionStartSpecificOutput(...)  # or register @_merge_specific.register for MyOutput","handlingStrategy":"type-guard","validationCode":"if not isinstance(output, (SessionStartSpecificOutput,)):  # supported types\n    raise TypeError(f\"unsupported hook-specific output: {type(output).__name__}\")","typeGuard":"from typing import TypeGuard\n\ndef is_mergeable(o: HookSpecificOutput) -> TypeGuard[SessionStartSpecificOutput]:\n    return isinstance(o, SessionStartSpecificOutput)","tryCatchPattern":"try:\n    decision = reduce_hook_results(results, event)\nexcept TypeError as e:\n    logger.warning(\"dropping unmergeable hook output: %s\", e)","preventionTips":["Return only HookSpecificOutput types the library defines","Register a merger when adding a new output subtype","Keep handler and reducer code versions in sync"],"tags":["typeerror","hooks","reducer","internal-invariant"],"backgroundTag":"unsupported-event-type","analyzedSha":"a1af029e6e73cb17c36bff823d227747b28e91e1","analyzedAt":"2026-08-29T11:43:24.718Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}