{"record":{"id":"aa2e1ca0c1bd07ed","repo":"langchain-ai/langgraph","slug":"handler-type-must-be-an-async-function-got-typ","errorCode":null,"errorMessage":"{handler_type} must be an async function, got {type(fn)}","messagePattern":"(.+?) must be an async function, got (.+?)","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"libs/sdk-py/langgraph_sdk/encryption/__init__.py","lineNumber":55,"sourceCode":"\nclass DuplicateHandlerError(Exception):\n    \"\"\"Raised when attempting to register a duplicate encryption/decryption handler.\"\"\"\n\n    pass\n\n\ndef _validate_handler(fn: typing.Callable, handler_type: str) -> None:\n    \"\"\"Validate that a handler function has the correct signature.\n\n    Args:\n        fn: The handler function to validate\n        handler_type: Description of the handler for error messages\n\n    Raises:\n        TypeError: If the handler is not an async function or has wrong parameter count\n    \"\"\"\n    if not inspect.iscoroutinefunction(fn):\n        raise TypeError(f\"{handler_type} must be an async function, got {type(fn)}\")\n\n    sig = inspect.signature(fn)\n    params = [\n        p\n        for p in sig.parameters.values()\n        if p.kind in (p.POSITIONAL_ONLY, p.POSITIONAL_OR_KEYWORD)\n    ]\n    if len(params) != 2:\n        raise TypeError(\n            f\"{handler_type} must accept exactly 2 parameters \"\n            f\"(ctx, data), got {len(params)}\"\n        )\n\n\nclass _EncryptDecorators:\n    \"\"\"Decorators for encryption handlers.\n\n    Provides @encryption.encrypt.blob and @encryption.encrypt.json decorators for","sourceCodeStart":37,"sourceCodeEnd":73,"githubUrl":"https://github.com/langchain-ai/langgraph/blob/38031739e551638e373fb553453256c23feeb41f/libs/sdk-py/langgraph_sdk/encryption/__init__.py#L37-L73","documentation":"Signature validation performed by _validate_handler in the encryption module at decoration time. Encryption/decryption handlers must be coroutine functions so they can perform non-blocking IO; inspect.iscoroutinefunction returned False, and the offending object's type is included in the message.","triggerScenarios":"Thrown at libs/sdk-py/langgraph_sdk/encryption/__init__.py:55 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":["Declare the handler with async def, e.g. async def encrypt_blob(ctx: EncryptionContext, blob: bytes) -> bytes","If wrapping an existing function, ensure the wrapper itself is async rather than returning a coroutine object"],"exampleFix":null,"handlingStrategy":"validation","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"analyzedSha":"38031739e551638e373fb553453256c23feeb41f","analyzedAt":"2026-08-26T18:02:49.312Z","contentChangedAt":"2026-08-26T18:02:49.312Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}