{"record":{"id":"03b8dd826553e82c","repo":"zylon-ai/private-gpt","slug":"block-cannot-be-none","errorCode":null,"errorMessage":"Block cannot be None","messagePattern":"Block cannot be None","errorType":"validation","errorClass":"ValueError","httpStatus":422,"severity":"error","filePath":"private_gpt/server/chat/chat_models.py","lineNumber":391,"sourceCode":"\n        # Check unique tools\n        if self.tools:\n            tool_names = [tool.name for tool in self.tools]\n            if len(tool_names) != len(set(tool_names)):\n                raise ValueError(\n                    \"Duplicate tool names found in the tools list.\"\n                    f\" Provided tools: {self.tools}\"\n                    f\" Unique tool names: {set(tool_names)}\"\n                )\n\n        # Check tool use and result blocks\n        tool_uses_ids: set[str] = set()\n        tool_results_ids: set[str] = set()\n        for message in self.messages:\n            if isinstance(message.content, list):\n                for block in message.content:\n                    if block is None:\n                        raise ValueError(\"Block cannot be None\")\n                    elif isinstance(block, ToolUseBlock):\n                        if message.role != \"assistant\":\n                            raise ValueError(\n                                f\"Tool use blocks can only be used in assistant messages: {message}\"\n                            )\n                        if block.id in tool_uses_ids:\n                            raise ValueError(f\"Duplicate tool use ID found: {block.id}\")\n                        tool_uses_ids.add(block.id)\n\n                    elif isinstance(block, ToolResultBlock):\n                        if block.tool_use_id not in tool_uses_ids:\n                            raise ValueError(\n                                f\"Tool result block references an unknown tool use ID: {block.tool_use_id}\"\n                            )\n                        tool_results_ids.add(block.tool_use_id)\n\n                    elif isinstance(block, TLDRBlock):\n                        if message.role != \"assistant\":","sourceCodeStart":373,"sourceCodeEnd":409,"githubUrl":"https://github.com/zylon-ai/private-gpt/blob/4a030776a31a901ad80b1bf4d7faa2c1a367efbb/private_gpt/server/chat/chat_models.py#L373-L409","documentation":"Second pass of block validation in ChatBody: while cross-checking tool_use/tool_result blocks across messages, any None block inside a list content raises this error. It is the same null-block defect as error 329, caught in the tool-consistency loop (which runs after basic validation and can be the first place a null slips through if the earlier loop shape differs).","triggerScenarios":"content arrays containing null alongside tool blocks, e.g. [null, ToolResultBlock(...)]; deserialized stored conversations with sparse block arrays; client SDKs emitting null for unsupported block types in tool loops.","commonSituations":"Persistent chat stores that leave null placeholders for deleted blocks; partial JSON round-trips of tool conversations; race conditions appending blocks while serializing.","solutions":["Sanitize content lists before sending: drop None blocks.","Fix block (de)serialization so every entry is a valid block object or removed.","On load from storage, repair histories: [b for b in content if b is not None]."],"exampleFix":"# before\nmsg.content = stored_blocks  # may contain None\n\n# after\nmsg.content = [b for b in stored_blocks if b is not None]","handlingStrategy":"validation","validationCode":"for m in messages:\n    if isinstance(m.get('content'), list):\n        m['content'] = [b for b in m['content'] if b is not None]","typeGuard":"def no_null_blocks(msgs: list[dict]) -> bool:\n    return all(\n        all(b is not None for b in m['content'])\n        for m in msgs if isinstance(m.get('content'), list)\n    )","tryCatchPattern":"except ValidationError as e:\n    if 'Block cannot be None' in str(e):\n        strip_null_blocks(messages); retry()\n    else:\n        raise","preventionTips":["Repair stored histories on load (drop null blocks)","Never append placeholder nulls during block streaming","Fuzz-test serializers with missing optional blocks"],"tags":["validation","content-blocks","null-safety","tools"],"backgroundTag":null,"analyzedSha":"4a030776a31a901ad80b1bf4d7faa2c1a367efbb","analyzedAt":"2026-08-15T03:51:26.951Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}