hasValidContent() only treated text/tool_use/tool_result blocks as valid content, so a user message containing only an image block was filtered out as empty. When it was the only non-system message, this left an empty messages array and Anthropic rejected the request.