aaif-goose/goose · info

No valid messages to send to Snowflake API

Error message

No valid messages to send to Snowflake API

What it means

create_request builds the Snowflake Cortex request payload: it formats the conversation, then unconditionally inserts the system message at index 0, and only afterwards checks snowflake_messages.is_empty(). Because the system message is always inserted first, the vector always has at least one element and this error is unreachable in the current code — it is dead guarding left over from a version that checked emptiness before the insert.

Source

Thrown at crates/goose-provider-types/src/formats/snowflake.rs:336

    }
}

/// Create a complete request payload for Snowflake's API
pub fn create_request(
    model_config: &ModelConfig,
    system: &str,
    messages: &[Message],
    tools: &[Tool],
) -> Result<Value> {
    let mut snowflake_messages = format_messages(messages);
    let system_spec = format_system(system);

    // Add system message to the beginning of the messages
    snowflake_messages.insert(0, system_spec);

    // Check if we have any messages to send
    if snowflake_messages.is_empty() {
        return Err(anyhow!("No valid messages to send to Snowflake API"));
    }

    // Detect description generation requests and exclude tools to prevent interference
    // with normal tool execution flow
    let is_description_request =
        system.contains("Reply with only a description in four words or less");

    let tool_specs = if is_description_request {
        // For description generation, don't include any tools to avoid confusion
        format_tools(&[])
    } else {
        format_tools(tools)
    };

    let mut payload = json!({
        "model": model_config.model_name,
        "messages": snowflake_messages,
        "max_tokens": model_config.max_output_tokens(),

View on GitHub (pinned to 3810898a74)

Solutions

  1. If you see this error, you are running modified code — check the local diff of snowflake.rs create_request
  2. If the intent is to require user content, move the emptiness check before the system insert (see exampleFix)
  3. Otherwise delete the dead check to avoid confusion

Example fix

// before
snowflake_messages.insert(0, system_spec);
if snowflake_messages.is_empty() {
    return Err(anyhow!("No valid messages to send to Snowflake API"));
}

// after - guard checks the real conversation, not the list we just grew
if snowflake_messages.is_empty() {
    return Err(anyhow!("No valid messages to send to Snowflake API"));
}
snowflake_messages.insert(0, system_spec);
Defensive patterns

Strategy: validation

Validate before calling

// the shipped guard is unreachable; validate inputs yourself before create_request
if messages.is_empty() {
    anyhow::bail!("conversation has no messages to send");
}
let payload = create_request(&model_config, system, messages, tools)?;

Type guard

fn has_sendable_messages(messages: &[Message]) -> bool {
    !messages.is_empty()
}

Prevention

When it happens

Trigger: Cannot fire with the code as shipped: format_messages output plus one inserted system message is never empty. You would only see it in a modified/reordered variant of create_request, or if a future refactor removes the unconditional insert.

Common situations: Hitting this in a fork where the insert(0, system_spec) line was removed or made conditional; static-analysis/audit work flagging the dead branch; tests asserting the old guard behavior.

Related errors


AI-assisted analysis of aaif-goose/goose@3810898a74 (2026-08-16). Data as JSON: /api/errors/70c526025c9e3a86. Report an issue: GitHub.