{"record":{"id":"163bbf036aab95b9","repo":"Hmbown/CodeWhale","slug":"antigravity-cloud-code-request-has-no-text-content","errorCode":null,"errorMessage":"Antigravity cloud-code request has no text contents","messagePattern":"Antigravity cloud-code request has no text contents","errorType":"validation","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/tui/src/client/cloud_code.rs","lineNumber":85,"sourceCode":"        };\n        let mut parts = Vec::new();\n        for block in &message.content {\n            match block {\n                ContentBlock::Text { text, .. } if !text.trim().is_empty() => {\n                    parts.push(json!({ \"text\": text }));\n                }\n                ContentBlock::Text { .. } => {}\n                _ => bail!(\n                    \"Antigravity cloud-code accepts text parts only; non-text content fails closed\"\n                ),\n            }\n        }\n        if !parts.is_empty() {\n            contents.push(json!({ \"role\": role, \"parts\": parts }));\n        }\n    }\n    if contents.is_empty() {\n        bail!(\"Antigravity cloud-code request has no text contents\");\n    }\n    let model = request.model.trim();\n    if model.is_empty() {\n        bail!(\"Antigravity cloud-code request is missing a model id\");\n    }\n    Ok(json!({\n        \"model\": model,\n        \"userAgent\": \"codewhale\",\n        \"request\": {\n            \"contents\": contents,\n        }\n    }))\n}\n\n/// Pull visible text out of a cloud-code SSE JSON object. Unknown shapes\n/// return `None` so the caller can fail closed instead of guessing.\npub fn extract_cloud_code_text(value: &Value) -> Option<String> {\n    if let Some(text) = value.pointer(\"/response/candidates/0/content/parts/0/text\") {","sourceCodeStart":67,"sourceCodeEnd":103,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/0c42157ee52f9d55af2b506d71b46249910f77d3/crates/tui/src/client/cloud_code.rs#L67-L103","documentation":"After iterating all messages and skipping empty/whitespace text blocks, the builder found zero `contents` entries to send and bails. This means every message either had no text blocks or only blank ones (non-text blocks would have failed earlier with the content-type error). Sending an empty conversation to cloud-code has no meaning, so the request is refused locally.","triggerScenarios":"A request where every message's text is empty or whitespace-only, e.g. a user turn of \"   \", or a message list composed solely of blank assistant messages.","commonSituations":"A UI that allows submitting an empty prompt; upstream trimming logic that empties messages (e.g. redaction) without dropping them; automated pipelines sending placeholder turns.","solutions":["Ensure at least one message contains non-whitespace text before submitting","Validate the prompt client-side and refuse empty submissions","Check any history-trimming/redaction step that may blank out message text in place"],"exampleFix":"// before\nlet text = \"   \"; // whitespace-only -> contents empty -> bail\n\n// after\nlet text = text.trim();\nanyhow::ensure!(!text.is_empty(), \"prompt must contain non-empty text\");","handlingStrategy":"validation","validationCode":"let has_text = request.messages.iter().any(|m| {\n    m.content.iter().any(|b| matches!(b, ContentBlock::Text { text, .. } if !text.trim().is_empty()))\n});\nanyhow::ensure!(has_text, \"refusing to send a request with no text contents\");","typeGuard":"fn has_nonempty_text(messages: &[ChatMessage]) -> bool {\n    messages.iter().any(|m| {\n        m.content.iter().any(|b| matches!(b, ContentBlock::Text { text, .. } if !text.trim().is_empty()))\n    })\n}","tryCatchPattern":"if !has_nonempty_text(&request.messages) {\n    return Ok(None); // nothing to say; skip the turn entirely\n}\nmatch client.create_message_stream(request).await { /* ... */ }","preventionTips":["Reject empty/whitespace prompt submissions in the UI layer","After any redaction or trimming pass, drop fully-emptied messages instead of keeping them","Unit-test request builders with blank-turn inputs"],"tags":["antigravity","cloud-code","empty-request","validation","rust"],"backgroundTag":"empty-request-body","analyzedSha":"0c42157ee52f9d55af2b506d71b46249910f77d3","analyzedAt":"2026-08-20T21:50:45.477Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}