{"record":{"id":"0754e33d676dde2f","repo":"Hmbown/CodeWhale","slug":"antigravity-cloud-code-does-not-accept-role-other","errorCode":null,"errorMessage":"Antigravity cloud-code does not accept role {other:?}","messagePattern":"Antigravity cloud-code does not accept role (.+?)","errorType":"validation","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/tui/src/client/cloud_code.rs","lineNumber":66,"sourceCode":"    };\n    if has_system_text {\n        return Err(CloudCodeRequestError::SystemPromptUnsupported.into());\n    }\n    if request\n        .tools\n        .as_ref()\n        .is_some_and(|tools| !tools.is_empty())\n    {\n        bail!(\n            \"Antigravity cloud-code tools are not implemented yet; send a text-only turn or use the google provider\"\n        );\n    }\n    let mut contents = Vec::new();\n    for message in &request.messages {\n        let role = match message.role.as_str() {\n            \"user\" => \"user\",\n            \"assistant\" | \"model\" => \"model\",\n            other => bail!(\"Antigravity cloud-code does not accept role {other:?}\"),\n        };\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() {","sourceCodeStart":48,"sourceCodeEnd":84,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/0c42157ee52f9d55af2b506d71b46249910f77d3/crates/tui/src/client/cloud_code.rs#L48-L84","documentation":"The cloud-code request builder maps each message role and only accepts `user`, `assistant`, and `model` (aliased). Any other role string is surfaced verbatim in the bail message. This is a strict contract check: cloud-code's contents array has no representation for other roles, so the builder refuses rather than mislabeling the message.","triggerScenarios":"A message whose `role` is anything besides user/assistant/model — most commonly `system` or `tool` — reaching the builder on an antigravity route. The message content itself does not matter; the role alone triggers it.","commonSituations":"A pipeline that injects `system` messages into the message list (cloud-code wants no system prompt at all, which is the separate SystemPromptUnsupported error), or tool-result messages with role `tool` from a generic agent loop replayed onto this provider.","solutions":["Remove or convert `system` messages before sending on this route (note cloud-code rejects system prompts entirely)","Drop `tool` role messages; tools are unsupported on this adapter anyway","Normalize roles: map `model`→assistant upstream so only user/assistant remain"],"exampleFix":"// before\nmessages.push(Message { role: \"system\".into(), .. }); // -> bail role \"system\"\n\n// after\nlet messages: Vec<_> = messages.into_iter().filter(|m| matches!(m.role.as_str(), \"user\" | \"assistant\" | \"model\")).collect();","handlingStrategy":"validation","validationCode":"for msg in &request.messages {\n    anyhow::ensure!(\n        matches!(msg.role.as_str(), \"user\" | \"assistant\" | \"model\"),\n        \"cloud-code rejects role {:?}\",\n        msg.role\n    );\n}","typeGuard":"fn cloud_code_roles_ok(messages: &[ChatMessage]) -> bool {\n    messages.iter().all(|m| matches!(m.role.as_str(), \"user\" | \"assistant\" | \"model\"))\n}","tryCatchPattern":"let request = sanitize_roles_for_cloud_code(request)?; // filter system/tool first\nmatch client.create_message_stream(request).await {\n    Ok(s) => Ok(s),\n    Err(err) if err.to_string().contains(\"does not accept role\") => {\n        Err(anyhow!(\"role rejected: sanitize message list before antigravity routes\"))\n    }\n    Err(err) => Err(err),\n}","preventionTips":["Extract system prompts upstream; cloud-code rejects them separately","Never replay `tool` role messages on antigravity routes","Normalize model→assistant at the boundary so only two roles flow"],"tags":["antigravity","cloud-code","message-role","request-validation","rust"],"backgroundTag":"unsupported-message-role","analyzedSha":"0c42157ee52f9d55af2b506d71b46249910f77d3","analyzedAt":"2026-08-20T21:50:45.477Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}