{"record":{"id":"c510744f63cd5873","repo":"aaif-goose/goose","slug":"activities-array-element-is-not-a-string","errorCode":null,"errorMessage":"'activities' array element is not a string","messagePattern":"'activities' array element is not a string","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/goose/src/agents/agent.rs","lineNumber":3859,"sourceCode":"        let (instructions, activities) =\n            if let Ok(json_content) = serde_json::from_str::<Value>(&clean_content) {\n                let instructions = json_content\n                    .get(\"instructions\")\n                    .ok_or_else(|| anyhow!(\"Missing 'instructions' in json response\"))?\n                    .as_str()\n                    .ok_or_else(|| anyhow!(\"instructions' is not a string\"))?\n                    .to_string();\n\n                let activities = json_content\n                    .get(\"activities\")\n                    .ok_or_else(|| anyhow!(\"Missing 'activities' in json response\"))?\n                    .as_array()\n                    .ok_or_else(|| anyhow!(\"'activities' is not an array'\"))?\n                    .iter()\n                    .map(|act| {\n                        act.as_str()\n                            .map(|s| s.to_string())\n                            .ok_or(anyhow!(\"'activities' array element is not a string\"))\n                    })\n                    .collect::<Result<_, _>>()?;\n\n                (instructions, activities)\n            } else {\n                tracing::warn!(\"Failed to parse JSON, falling back to string parsing\");\n                // If we can't get valid JSON, try string parsing\n                // Use split_once to get the content after \"Instructions:\".\n                let after_instructions = content\n                    .split_once(\"instructions:\")\n                    .map(|(_, rest)| rest)\n                    .unwrap_or(&content);\n\n                // Split once more to separate instructions from activities.\n                let (instructions_part, activities_text) = after_instructions\n                    .split_once(\"activities:\")\n                    .unwrap_or((after_instructions, \"\"));\n","sourceCodeStart":3841,"sourceCodeEnd":3877,"githubUrl":"https://github.com/aaif-goose/goose/blob/3810898a7447ec3299be72e223d3570a7aabf0ab/crates/goose/src/agents/agent.rs#L3841-L3877","documentation":"Thrown during recipe response parsing when \"activities\" is an array but contains at least one non-string element (as_str() returns None for that element). The model mixed objects, numbers, or nulls into the activities list.","triggerScenarios":"Model returns {\"activities\": [{\"name\": \"step\"}, \"run tests\"]} — an object element among strings — during recipe generation.","commonSituations":"Models emitting structured activity objects with extra metadata; mixed-language outputs; partial JSON degradation on long generations.","solutions":["Retry the recipe generation","Use a stronger model","Clean up / shorten the source conversation","Fall back to hand-authoring the recipe"],"exampleFix":null,"handlingStrategy":"retry","validationCode":"// Rust — every activities element must be a string\nlet ok = json.get(\"activities\").and_then(|a| a.as_array())\n    .map(|a| a.iter().all(|e| e.is_string())).unwrap_or(false);\nif !ok { /* regenerate */ }","typeGuard":null,"tryCatchPattern":"// Rust — retry on element-type errors from generation\nmatch generate_recipe(&agent, &conversation).await {\n    Ok(r) => Ok(r),\n    Err(e) if e.to_string().contains(\"array element is not a string\") => retry_or_fallback(e),\n    Err(e) => Err(e),\n}","preventionTips":["Retry before debugging — mixed-type arrays are sampling artifacts","Keep source conversations short and structured"],"tags":["recipe","json","llm-output","parsing","retryable"],"backgroundTag":null,"analyzedSha":"3810898a7447ec3299be72e223d3570a7aabf0ab","analyzedAt":"2026-08-16T10:14:26.282Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}