aaif-goose/goose · error
No messages found in scenario result
Error message
No messages found in scenario result
What it means
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.
Source
Thrown at crates/goose-cli/src/scenario_tests/scenario_runner.rs:43
pub messages: Conversation,
pub error: Option<String>,
}
impl ScenarioResult {
pub fn message_contents(&self) -> Vec<String> {
self.messages
.iter()
.flat_map(|msg| &msg.content)
.map(|content| content.as_text().unwrap_or("").to_string())
.collect()
}
pub fn last_message(&self) -> Result<String, anyhow::Error> {
let message_contents = self.message_contents();
message_contents
.last()
.cloned()
.ok_or_else(|| anyhow::anyhow!("No messages found in scenario result"))
}
}
pub async fn run_scenario<F>(
test_name: &str,
message_generator: MessageGenerator<'_>,
providers_to_skip: Option<&[&str]>,
validator: F,
) -> Result<()>
where
F: Fn(&ScenarioResult) -> Result<()> + Send + Sync + 'static,
{
if let Ok(only_provider) = std::env::var("GOOSE_TEST_PROVIDER") {
let active_providers = get_provider_configs();
let config = active_providers
.iter()
.find(|c| c.name.to_lowercase() == only_provider.to_lowercase())
.ok_or_else(|| {View on GitHub (pinned to 3810898a74)
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.
Example fix
// before
validator(&result)
// after
let check = |result: &ScenarioResult| -> Result<()> {
if let Some(err) = &result.error {
return Err(anyhow::anyhow!("scenario errored: {err}"));
}
let last = result.last_message()?;
assert!(last.contains("expected"));
Ok(())
}; Defensive patterns
Strategy: type-guard
Type guard
fn has_messages(result: &ScenarioResult) -> bool {
!result.message_contents().is_empty()
}
// in the validator:
if !has_messages(&result) {
return Err(anyhow::anyhow!("no messages (run error: {:?})", result.error));
}
let last = result.last_message()?; Try / catch
match result.last_message() {
Err(e) if e.to_string().contains("No messages found") => {
return Err(anyhow::anyhow!("scenario produced no output; error={:?}", result.error));
}
r => r?,
} Prevention
- Always check result.error before asserting on message content.
- Fail with a diagnostic that includes the underlying run error when the transcript is empty.
When it happens
Trigger: 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.
Common situations: Scenario tests whose validator assumes at least one reply; runs where credentials expired mid-suite so every scenario starts empty.
Related errors
- Some providers in skip list don't exist
- Test '{}' failed for {} provider(s)
- Invalid provider id: provider id cannot be empty
- Invalid provider id: {id}
- Resource '${fallbackUri}' returned no contents
AI-assisted analysis of aaif-goose/goose@3810898a74 (2026-08-16).
Data as JSON: /api/errors/dcbc9b829ccd1d25.
Report an issue: GitHub.