{"record":{"id":"51eebc8b4abc8ee0","repo":"langchain-ai/deepagents","slug":"failed-to-parse-hook-interrupt","errorCode":null,"errorMessage":"Failed to parse hook interrupt","messagePattern":"Failed to parse hook interrupt","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"libs/code/deepagents_code/hooks/manager.py","lineNumber":541,"sourceCode":"            payload: Raw LangGraph interrupt value.\n\n        Returns:\n            Resume value for `Command(resume=...)`.\n\n        Raises:\n            RuntimeError: If hooks are unavailable, or the payload is not a\n                parseable hook invocation.\n        \"\"\"\n        from deepagents_code.hooks.client import fulfill_hook_interrupt\n\n        runtime = self._runtime\n        if runtime is None:\n            msg = \"Received hook invocation interrupt without a HooksRuntime\"\n            raise RuntimeError(msg)\n        resume = await fulfill_hook_interrupt(runtime, payload)\n        if resume is None:\n            msg = \"Failed to parse hook interrupt\"\n            raise RuntimeError(msg)\n        return resume\n\n    async def fulfill_pending_interrupts(\n        self,\n        pending: Mapping[str, object],\n    ) -> dict[str, dict[str, object]]:\n        \"\"\"Execute a batch of server-owned hook interrupts.\n\n        Args:\n            pending: LangGraph interrupt id to raw interrupt payload.\n\n        Returns:\n            Resume values keyed by interrupt id.\n\n        Raises:\n            RuntimeError: If hooks are unavailable, or a payload is not a\n                parseable hook invocation.\n        \"\"\"","sourceCodeStart":523,"sourceCodeEnd":559,"githubUrl":"https://github.com/langchain-ai/deepagents/blob/a1af029e6e73cb17c36bff823d227747b28e91e1/libs/code/deepagents_code/hooks/manager.py#L523-L559","documentation":"After obtaining a runtime, fulfill_interrupt calls fulfill_hook_interrupt, which returns None when the interrupt payload cannot be parsed as a Hooks v2 hook invocation (not a valid HookInvocationResponse shape / fails identity validation). The manager converts that None into a RuntimeError so callers get a clear failure instead of an opaque downstream error.","triggerScenarios":"Passing an interrupt payload to fulfill_interrupt that is not a well-formed hook invocation payload — wrong keys, missing invocation_id/snapshot_id, or a payload that fails parse_hook_resume_value validation (see the id-mismatch errors).","commonSituations":"Manually constructed or hand-edited interrupt payloads; payloads from an older Hooks version parsed with a newer adapter; grabbing an interrupt from graph state that is actually a different interrupt type (tool approval, not a hook).","solutions":["Log and inspect the raw payload; confirm it matches the Hooks v2 invocation interrupt shape (use is_hook_interrupt_payload to pre-check)","Re-fetch the payload from the pending interrupts map rather than reconstructing it manually","If the payload came from an older version, migrate or regenerate the interrupt instead of resuming it directly","Wrap fulfillment and surface the payload id in your own error handling to aid diagnosis"],"exampleFix":"// before\nawait manager.fulfill_interrupt(interrupt_data)  # unvalidated\n\n// after\nfrom deepagents_code.hooks.interrupt import is_hook_interrupt_payload\nif is_hook_interrupt_payload(interrupt_data):\n    await manager.fulfill_interrupt(interrupt_data)\nelse:\n    raise ValueError(f\"Not a hook interrupt payload: {interrupt_data!r}\")","handlingStrategy":"validation","validationCode":"from deepagents_code.hooks.interrupt import is_hook_interrupt_payload\n\nif not is_hook_interrupt_payload(payload):\n    raise ValueError(\"interrupt is not a Hooks v2 invocation payload\")\n","typeGuard":"def is_valid_hook_interrupt(payload: object) -> bool:\n    from deepagents_code.hooks.interrupt import is_hook_interrupt_payload\n    return isinstance(payload, dict) and is_hook_interrupt_payload(payload)\n","tryCatchPattern":"try:\n    resume = await manager.fulfill_interrupt(payload)\nexcept RuntimeError as exc:\n    if \"Failed to parse hook interrupt\" in str(exc):\n        logger.error(\"unparseable hook payload: %r\", payload)\n        resume = None  # skip or regenerate the interrupt\n    else:\n        raise\n","preventionTips":["Pre-check payloads with is_hook_interrupt_payload before fulfilling","Never hand-edit or manually reconstruct interrupt payloads","Regenerate interrupts from persisted state when upgrading across Hooks versions"],"tags":["hooks","interrupt","payload-parsing"],"backgroundTag":"hook-interrupt-payload-invalid","analyzedSha":"a1af029e6e73cb17c36bff823d227747b28e91e1","analyzedAt":"2026-08-29T11:43:24.718Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}