{"record":{"id":"cac42e9c7cab6645","repo":"zylon-ai/private-gpt","slug":"block-cannot-be-none-message","errorCode":null,"errorMessage":"Block cannot be None: {message}","messagePattern":"Block cannot be None: (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":422,"severity":"error","filePath":"private_gpt/server/chat/chat_models.py","lineNumber":321,"sourceCode":"        if self.frequency_penalty and self.frequency_penalty < 0:\n            self.frequency_penalty = None\n\n        if self.seed and self.seed < 0:\n            self.seed = None\n\n        if self.max_tokens is not None and self.max_tokens <= 0:\n            self.max_tokens = None\n\n        if not self.messages:\n            raise ValueError(\"Messages cannot be empty\")\n\n        for message in self.messages:\n            if not message.content:\n                raise ValueError(f\"Message content cannot be empty: {message}\")\n            if isinstance(message.content, list):\n                for block in message.content:\n                    if block is None:\n                        raise ValueError(f\"Block cannot be None: {message}\")\n\n        if self.messages[-1].role not in self._valid_last_message_roles:\n            raise ValueError(\n                f\"Last message role must be one of {self._valid_last_message_roles}, but got {self.messages[-1].role}\"\n            )\n\n        # Check tools and tool choice\n        if self.tools and self.tool_choice and self.tool_choice.type == \"tool\":\n            if not self.tools:\n                raise ValueError(\"Tool choice is set, but no tools are provided.\")\n            if self.tool_choice.name not in [tool.name for tool in self.tools]:\n                raise ValueError(\n                    f\"Tool choice '{self.tool_choice}' is not in the provided tools.\"\n                )\n\n        if not self.tools and self.tool_context:\n            raise ValueError(\n                \"Tool context is provided, but no tools are specified. \"","sourceCodeStart":303,"sourceCodeEnd":339,"githubUrl":"https://github.com/zylon-ai/private-gpt/blob/4a030776a31a901ad80b1bf4d7faa2c1a367efbb/private_gpt/server/chat/chat_models.py#L303-L339","documentation":"When message.content is a list of content blocks, the ChatBody validator walks the blocks and rejects any None entry. A null block means malformed block serialization upstream (e.g. a block that failed to construct was appended as None); the error message includes the whole message for context.","triggerScenarios":"Content arrays containing literal null: {\"role\":\"user\",\"content\":[null, {\"type\":\"text\",\"text\":\"hi\"}]}; JSON built by mapping over blocks where one element failed conversion to None; deserializing stored conversations with missing block entries.","commonSituations":"Storing chat history as sparse arrays (deleted blocks become null); client SDKs that emit null for unsupported block types; partial block JSON round-trips.","solutions":["Filter nulls out of content arrays before sending: content=[b for b in blocks if b is not None].","Fix the block serialization so unsupported blocks are skipped, not emitted as null.","Validate stored history on load and drop/repair null blocks."],"exampleFix":"# before\ncontent=[block for block in raw_blocks]  # raw_blocks may contain None\n\n# after\ncontent=[block for block in raw_blocks if block 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 blocks_valid(content: list | str) -> bool:\n    if isinstance(content, list):\n        return all(b is not None for b in content)\n    return bool(content)","tryCatchPattern":"except ValidationError as e:\n    if 'Block cannot be None' in str(e):\n        strip_null_blocks(messages); retry_request()\n    else:\n        raise","preventionTips":["Never store chat history with null block placeholders","Sanitize deserialized histories before re-sending","Skip unsupported blocks at serialization time instead of emitting null"],"tags":["validation","content-blocks","null-safety","chat-api"],"backgroundTag":null,"analyzedSha":"4a030776a31a901ad80b1bf4d7faa2c1a367efbb","analyzedAt":"2026-08-15T03:51:26.951Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}