{"record":{"id":"6ba66112f3631b45","repo":"zed-industries/zed","slug":"request-must-contain-at-least-one-content-item","errorCode":null,"errorMessage":"Request must contain at least one content item","messagePattern":"Request must contain at least one content item","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/google_ai/src/google_ai.rs","lineNumber":85,"sourceCode":"            .boxed())\n    } else {\n        let mut text = String::new();\n        response.body_mut().read_to_string(&mut text).await?;\n        Err(anyhow!(\n            \"error during streamGenerateContent, status code: {:?}, body: {}\",\n            response.status(),\n            text\n        ))\n    }\n}\n\npub fn validate_generate_content_request(request: &GenerateContentRequest) -> Result<()> {\n    if request.model.is_empty() {\n        bail!(\"Model must be specified\");\n    }\n\n    if request.contents.is_empty() {\n        bail!(\"Request must contain at least one content item\");\n    }\n\n    if let Some(user_content) = request\n        .contents\n        .iter()\n        .find(|content| content.role == Role::User)\n        && user_content.parts.is_empty()\n    {\n        bail!(\"User content must contain at least one part\");\n    }\n\n    Ok(())\n}\n\n#[derive(Debug, Serialize, Deserialize)]\npub enum Task {\n    #[serde(rename = \"generateContent\")]\n    GenerateContent,","sourceCodeStart":67,"sourceCodeEnd":103,"githubUrl":"https://github.com/zed-industries/zed/blob/5a9b9558db01a6b906cec2fb70a797affdc58cdd/crates/google_ai/src/google_ai.rs#L67-L103","documentation":"validate_generate_content_request rejects requests whose 'contents' vector is empty. The API requires at least one content item (normally a user turn) to generate against; an empty conversation has nothing to act on, so the guard fails the request client-side before any network call.","triggerScenarios":"Sending a request built from an empty message list; upstream filtering that removes every message (e.g. all turns were unsupported types) before the request is assembled; tests or scaffolding sending placeholder requests.","commonSituations":"User submits empty input and the caller forwards it anyway; a summarization or compaction path empties the history; message-mapping code filters out all messages for the target provider.","solutions":["Ensure at least one user message is present before sending","Skip the API call entirely when the conversation is empty rather than constructing a request","Audit upstream filtering and mapping code that could drop all messages"],"exampleFix":"// before\nlet contents = messages.iter().filter(|m| supported(m)).map(to_content).collect::<Vec<_>>();\nlet request = GenerateContentRequest { model, contents, ..Default::default() }; // contents may be empty -> bail\n\n// after\nif contents.is_empty() {\n    anyhow::bail!(\"nothing to send: all messages were filtered out\");\n}\nlet request = GenerateContentRequest { model, contents, ..Default::default() };","handlingStrategy":"validation","validationCode":"// before calling the API\nanyhow::ensure!(!request.contents.is_empty(), \"contents must not be empty\");","typeGuard":"fn has_content(request: &GenerateContentRequest) -> bool {\n    !request.contents.is_empty()\n}","tryCatchPattern":null,"preventionTips":["Skip the API call when the conversation is empty rather than building a request","Audit message-filtering code paths that can drop every message","Cover empty-history edge cases in tests of the mapping layer"],"tags":["google-ai","request-validation","llm-provider"],"backgroundTag":"empty-request-payload","analyzedSha":"5a9b9558db01a6b906cec2fb70a797affdc58cdd","analyzedAt":"2026-08-20T19:29:52.058Z","contentChangedAt":"2026-08-20T19:29:52.058Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}