{"record":{"id":"6ab9eff11549798a","repo":"unslothai/unsloth","slug":"unsupported-content-block-type-btype-r-in-a-user","errorCode":null,"errorMessage":"unsupported content block type {btype!r} in a user message","messagePattern":"unsupported content block type (.+?) in a user message","errorType":"validation","errorClass":"ValueError","httpStatus":422,"severity":"error","filePath":"studio/backend/models/inference.py","lineNumber":2541,"sourceCode":"        if not isinstance(data, dict):\n            return data\n        content = data.get(\"content\")\n        if data.get(\"role\") == \"assistant\":\n            # Coerce only an explicit null (resumed tool-only turn). A missing\n            # content key stays malformed so the required-field check still 400s.\n            if \"content\" in data and content is None:\n                return {**data, \"content\": \"\"}\n            return data\n        if isinstance(content, list):\n            for block in content:\n                btype = (\n                    block.get(\"type\") if isinstance(block, dict) else getattr(block, \"type\", None)\n                )\n                # Guard the value: a non-string type is unsupported too, and a\n                # membership test on an unhashable value would raise TypeError\n                # (escaping as a 500 instead of a clean 400).\n                if not isinstance(btype, str) or btype not in _KNOWN_ANTHROPIC_BLOCK_TYPES:\n                    raise ValueError(f\"unsupported content block type {btype!r} in a user message\")\n        return data\n\n\nclass AnthropicTool(BaseModel):\n    # User-defined client tools have input_schema; Anthropic-schema client tools\n    # and server tools use type/name.\n    type: Optional[str] = None\n    name: Optional[str] = None\n    description: Optional[str] = None\n    input_schema: Optional[dict] = None\n    model_config = {\"extra\": \"allow\"}\n\n\nclass AnthropicMessagesRequest(BaseModel):\n    model: str = \"default\"\n    max_tokens: Optional[int] = None\n    messages: list[AnthropicMessage]\n    system: Optional[Union[str, list]] = None","sourceCodeStart":2523,"sourceCodeEnd":2559,"githubUrl":"https://github.com/unslothai/unsloth/blob/203007d19051dcd2ae33876786d117c99f6b0368/studio/backend/models/inference.py#L2523-L2559","documentation":"Raised by an Anthropic messages-request validator when a user message's content list contains a block whose type is not in _KNOWN_ANTHROPIC_BLOCK_TYPES, or whose type is not a string at all (the isinstance check also prevents an unhashable type value raising TypeError and escaping as a 500). It converts unsupported/absent block types into a clean 400.","triggerScenarios":"POST /v1/messages with user content [{\"type\": \"document\", ...}], [{\"type\": 123}], or [{}] (missing type). Sending Anthropic server-tool types the backend has not modeled also triggers it.","commonSituations":"Porting a client from Anthropic's full API which supports more block types (document, thinking, redacted_thinking, server tools) than this backend models; typos in block type strings; blocks built dynamically where type ends up None or non-string.","solutions":["Restrict user-message blocks to the supported types (text, image, tool_use, tool_result — check _KNOWN_ANTHROPIC_BLOCK_TYPES in the repo).","Convert documents/PDFs to text blocks client-side before sending.","Validate every block has a string 'type' key before serialization."],"exampleFix":"# before\ncontent = [{\"type\": \"document\", \"source\": {...}}]  # unsupported here\n\n# after\ncontent = [{\"type\": \"text\", \"text\": extracted_document_text}]","handlingStrategy":"validation","validationCode":"KNOWN = {'text', 'image', 'tool_use', 'tool_result'}  # mirror _KNOWN_ANTHROPIC_BLOCK_TYPES\ndef valid_user_blocks(content) -> bool:\n    if not isinstance(content, list):\n        return True\n    return all(\n        isinstance(b, dict) and isinstance(b.get('type'), str) and b['type'] in KNOWN\n        for b in content\n    )","typeGuard":"def is_supported_block(b) -> bool:\n    return isinstance(b, dict) and isinstance(b.get('type'), str) and b['type'] in {\n        'text', 'image', 'tool_use', 'tool_result'\n    }","tryCatchPattern":null,"preventionTips":["Check _KNOWN_ANTHROPIC_BLOCK_TYPES in the repo for the exact accepted set","Convert documents/PDFs to text blocks before sending","Always emit a string 'type' key on generated blocks"],"tags":["pydantic","validation","anthropic","content-blocks","messages-api"],"backgroundTag":null,"analyzedSha":"203007d19051dcd2ae33876786d117c99f6b0368","analyzedAt":"2026-08-15T02:48:39.846Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}