{"record":{"id":"4e4bce1d1b75edcd","repo":"langchain-ai/langgraph","slug":"ch-r-is-not-a-valid-interleave-projections-chann","errorCode":null,"errorMessage":"{ch!r} is not a valid interleave_projections channel{hint}. Supported channels: {', '.join(SUPPORTED_INTERLEAVE_CHANNELS)}, or an extension name.","messagePattern":"(.+?) is not a valid interleave_projections channel(.+?)\\. Supported channels: (.+?), or an extension name\\.","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"libs/sdk-py/langgraph_sdk/stream/decoders.py","lineNumber":45,"sourceCode":"#: to the extension/``custom:`` fallback would subscribe to a channel that never\n#: matches and silently yield nothing, so they are rejected up front (fail\n#: closed). ``lifecycle`` is control-plane (drives run output/interrupt); ``tools``\n#: is the wire alias for the public ``tool_calls`` channel.\nRESERVED_INTERLEAVE_CHANNELS = frozenset({\"lifecycle\", \"tools\", \"input\"})\n\n\ndef validate_interleave_channels(channels: list[str]) -> None:\n    \"\"\"Reject reserved protocol channel names before they hit the fallback.\n\n    Genuine extension names pass through untouched; only names that\n    ``infer_channel`` treats as built-in methods without an interleave decoder\n    are rejected, so a typo'd or unsupported protocol channel surfaces an error\n    instead of an empty stream.\n    \"\"\"\n    for ch in channels:\n        if ch in RESERVED_INTERLEAVE_CHANNELS:\n            hint = ' (use \"tool_calls\")' if ch == \"tools\" else \"\"\n            raise ValueError(\n                f\"{ch!r} is not a valid interleave_projections channel{hint}. \"\n                f\"Supported channels: {', '.join(SUPPORTED_INTERLEAVE_CHANNELS)}, \"\n                \"or an extension name.\"\n            )\n\n\ndef _event_namespace(params_field: Any) -> list[str]:\n    if not isinstance(params_field, dict):\n        return []\n    namespace = params_field.get(\"namespace\") or []\n    return list(namespace) if isinstance(namespace, list) else []\n\n\ndef _message_event_id(data: dict[str, Any]) -> str | None:\n    message_id = data.get(\"id\") or data.get(\"message_id\")\n    return str(message_id) if message_id is not None else None\n\n","sourceCodeStart":27,"sourceCodeEnd":63,"githubUrl":"https://github.com/langchain-ai/langgraph/blob/38031739e551638e373fb553453256c23feeb41f/libs/sdk-py/langgraph_sdk/stream/decoders.py#L27-L63","documentation":"Error \"{ch!r} is not a valid interleave_projections channel{hint}. Supported channels: {', '.join(SUPPORTED_INTERLEAVE_CHANNELS)}, or an extension name.\" thrown in langchain-ai/langgraph.","triggerScenarios":"Thrown at libs/sdk-py/langgraph_sdk/stream/decoders.py:45 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":[],"exampleFix":null,"handlingStrategy":null,"validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"analyzedSha":"38031739e551638e373fb553453256c23feeb41f","analyzedAt":"2026-08-26T18:02:49.312Z","schemaVersion":2},"datasetVersion":"2026-08-26T21:11:00.512Z"}