{"record":{"id":"dcbc9b829ccd1d25","repo":"aaif-goose/goose","slug":"no-messages-found-in-scenario-result","errorCode":null,"errorMessage":"No messages found in scenario result","messagePattern":"No messages found in scenario result","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/goose-cli/src/scenario_tests/scenario_runner.rs","lineNumber":43,"sourceCode":"    pub messages: Conversation,\n    pub error: Option<String>,\n}\n\nimpl ScenarioResult {\n    pub fn message_contents(&self) -> Vec<String> {\n        self.messages\n            .iter()\n            .flat_map(|msg| &msg.content)\n            .map(|content| content.as_text().unwrap_or(\"\").to_string())\n            .collect()\n    }\n\n    pub fn last_message(&self) -> Result<String, anyhow::Error> {\n        let message_contents = self.message_contents();\n        message_contents\n            .last()\n            .cloned()\n            .ok_or_else(|| anyhow::anyhow!(\"No messages found in scenario result\"))\n    }\n}\n\npub async fn run_scenario<F>(\n    test_name: &str,\n    message_generator: MessageGenerator<'_>,\n    providers_to_skip: Option<&[&str]>,\n    validator: F,\n) -> Result<()>\nwhere\n    F: Fn(&ScenarioResult) -> Result<()> + Send + Sync + 'static,\n{\n    if let Ok(only_provider) = std::env::var(\"GOOSE_TEST_PROVIDER\") {\n        let active_providers = get_provider_configs();\n        let config = active_providers\n            .iter()\n            .find(|c| c.name.to_lowercase() == only_provider.to_lowercase())\n            .ok_or_else(|| {","sourceCodeStart":25,"sourceCodeEnd":61,"githubUrl":"https://github.com/aaif-goose/goose/blob/3810898a7447ec3299be72e223d3570a7aabf0ab/crates/goose-cli/src/scenario_tests/scenario_runner.rs#L25-L61","documentation":"ScenarioResult::last_message() was called when message_contents() is empty — the recorded message history after the scenario run contains no messages at all. Validators typically hit this when the provider failed before emitting any assistant output, so the scenario 'result' is an empty transcript plus an error string.","triggerScenarios":"A validator calling result.last_message()? when the run aborted immediately: provider auth failure, replay file mismatch surfacing as result.error, or all messages lost because process_message errored on the first turn.","commonSituations":"Scenario tests whose validator assumes at least one reply; runs where credentials expired mid-suite so every scenario starts empty.","solutions":["Check result.error first — an empty transcript almost always means the run failed; surface that error instead of assuming a missing message.","Guard the validator: return a clearer failure when message_contents().is_empty().","Fix the underlying provider/run failure so the scenario actually produces messages."],"exampleFix":"// before\nvalidator(&result)\n\n// after\nlet check = |result: &ScenarioResult| -> Result<()> {\n    if let Some(err) = &result.error {\n        return Err(anyhow::anyhow!(\"scenario errored: {err}\"));\n    }\n    let last = result.last_message()?;\n    assert!(last.contains(\"expected\"));\n    Ok(())\n};","handlingStrategy":"type-guard","validationCode":null,"typeGuard":"fn has_messages(result: &ScenarioResult) -> bool {\n    !result.message_contents().is_empty()\n}\n\n// in the validator:\nif !has_messages(&result) {\n    return Err(anyhow::anyhow!(\"no messages (run error: {:?})\", result.error));\n}\nlet last = result.last_message()?;","tryCatchPattern":"match result.last_message() {\n    Err(e) if e.to_string().contains(\"No messages found\") => {\n        return Err(anyhow::anyhow!(\"scenario produced no output; error={:?}\", result.error));\n    }\n    r => r?,\n}","preventionTips":["Always check result.error before asserting on message content.","Fail with a diagnostic that includes the underlying run error when the transcript is empty."],"tags":["testing","scenarios","validation","empty-state"],"backgroundTag":null,"analyzedSha":"3810898a7447ec3299be72e223d3570a7aabf0ab","analyzedAt":"2026-08-16T10:14:26.282Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}