zed-industries/zed · error

Request must contain at least one content item

Error message

Request must contain at least one content item

What it means

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.

Source

Thrown at crates/google_ai/src/google_ai.rs:85

            .boxed())
    } else {
        let mut text = String::new();
        response.body_mut().read_to_string(&mut text).await?;
        Err(anyhow!(
            "error during streamGenerateContent, status code: {:?}, body: {}",
            response.status(),
            text
        ))
    }
}

pub fn validate_generate_content_request(request: &GenerateContentRequest) -> Result<()> {
    if request.model.is_empty() {
        bail!("Model must be specified");
    }

    if request.contents.is_empty() {
        bail!("Request must contain at least one content item");
    }

    if let Some(user_content) = request
        .contents
        .iter()
        .find(|content| content.role == Role::User)
        && user_content.parts.is_empty()
    {
        bail!("User content must contain at least one part");
    }

    Ok(())
}

#[derive(Debug, Serialize, Deserialize)]
pub enum Task {
    #[serde(rename = "generateContent")]
    GenerateContent,

View on GitHub (pinned to 5a9b9558db)

Solutions

  1. Ensure at least one user message is present before sending
  2. Skip the API call entirely when the conversation is empty rather than constructing a request
  3. Audit upstream filtering and mapping code that could drop all messages

Example fix

// before
let contents = messages.iter().filter(|m| supported(m)).map(to_content).collect::<Vec<_>>();
let request = GenerateContentRequest { model, contents, ..Default::default() }; // contents may be empty -> bail

// after
if contents.is_empty() {
    anyhow::bail!("nothing to send: all messages were filtered out");
}
let request = GenerateContentRequest { model, contents, ..Default::default() };
Defensive patterns

Strategy: validation

Validate before calling

// before calling the API
anyhow::ensure!(!request.contents.is_empty(), "contents must not be empty");

Type guard

fn has_content(request: &GenerateContentRequest) -> bool {
    !request.contents.is_empty()
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of zed-industries/zed@5a9b9558db (2026-08-20). Data as JSON: /api/errors/6ba66112f3631b45. Report an issue: GitHub.