{"record":{"id":"b50eece139b03b36","repo":"aaif-goose/goose","slug":"activities-is-not-an-array","errorCode":null,"errorMessage":"'activities' is not an array'","messagePattern":"'activities' is not an array'","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/goose/src/agents/agent.rs","lineNumber":3854,"sourceCode":"            .and_then(|caps| caps.get(1).map(|m| m.as_str()))\n            .unwrap_or(&content)\n            .trim()\n            .to_string();\n\n        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","sourceCodeStart":3836,"sourceCodeEnd":3872,"githubUrl":"https://github.com/aaif-goose/goose/blob/3810898a7447ec3299be72e223d3570a7aabf0ab/crates/goose/src/agents/agent.rs#L3836-L3872","documentation":"Thrown during recipe response parsing when the \"activities\" key exists but its value is not a JSON array (as_array() fails) — for example an object or a plain string. Activities must be a list of strings for the recipe builder.","triggerScenarios":"Model returns {\"activities\": \"1. do x 2. do y\"} or {\"activities\": {\"1\": \"...\"}} instead of a list during recipe generation.","commonSituations":"Models formatting activities as prose or numbered maps; schema drift on smaller/local models; output truncation producing malformed tails.","solutions":["Retry the generation","Use a stronger or officially supported model","Shorten the conversation being converted to reduce format drift","Write the recipe YAML by hand"],"exampleFix":null,"handlingStrategy":"retry","validationCode":"// Rust — verify activities is an array before accepting the response\nlet ok = json.get(\"activities\").and_then(|a| a.as_array()).is_some();\nif !ok { /* regenerate */ }","typeGuard":null,"tryCatchPattern":"// Rust — retry on shape errors, surface everything else\nmatch generate_recipe(&agent, &conversation).await {\n    Ok(r) => Ok(r),\n    Err(e) if e.to_string().contains(\"is not an array\") => retry_or_fallback(e),\n    Err(e) => Err(e),\n}","preventionTips":["Retry on shape errors; switch models only if failures repeat","Avoid prompting tweaks that encourage prose-formatted activity lists"],"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"}