{"record":{"id":"6ca1fbb2e440e38d","repo":"aaif-goose/goose","slug":"planner-returned-no-user-visible-content","errorCode":null,"errorMessage":"Planner returned no user-visible content","messagePattern":"Planner returned no user-visible content","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/goose-cli/src/session/mod.rs","lineNumber":1337,"sourceCode":"        let plan_prompt = self.agent.get_plan_prompt(&self.session_id).await?;\n        let provider_messages = planner_provider_messages(&plan_messages);\n        output::show_thinking();\n        let (plan_response, _usage) = goose::session_context::with_session_id(\n            Some(self.session_id.clone()),\n            reasoner.complete(\n                &model_config,\n                &plan_prompt,\n                provider_messages.messages(),\n                &[],\n            ),\n        )\n        .await?;\n        let classifier_text = planner_classification_text(&plan_response);\n        let plan_response = plan_response.user_visible_content();\n        output::render_message(&plan_response, self.debug);\n        output::hide_thinking();\n        let classifier_text = classifier_text?;\n        anyhow::ensure!(\n            !plan_response.content.is_empty(),\n            \"Planner returned no user-visible content\"\n        );\n        let planner_response_type = classify_planner_response(\n            &self.session_id,\n            classifier_text,\n            self.agent.provider().await?,\n            self.agent\n                .model_config_for_session(&self.session_id)\n                .await?,\n        )\n        .await?;\n\n        match planner_response_type {\n            PlannerResponseType::Plan => {\n                println!();\n                let should_act = match cliclack::confirm(\n                    \"Do you want to clear message history & act on this plan?\",","sourceCodeStart":1319,"sourceCodeEnd":1355,"githubUrl":"https://github.com/aaif-goose/goose/blob/3810898a7447ec3299be72e223d3570a7aabf0ab/crates/goose-cli/src/session/mod.rs#L1319-L1355","documentation":"After the planner reply arrives, goose renders user_visible_content() and then asserts the content is non-empty before classifying the response. A planner reply whose user-visible content is empty (no content at all, or all of it hidden) trips this ensure. The render happens before the check, and the classifier error surfaces after rendering.","triggerScenarios":"Plan-mode requests where the planner model returns an empty completion or a response whose content is entirely user-invisible (e.g. reasoning-only or filtered output).","commonSituations":"Same class as the agent-visible variant: misconfigured planner model, provider returning empty content, or aggressive response filtering.","solutions":["Retry the plan request","Validate GOOSE_PLANNER_MODEL and provider credentials","Inspect the raw response with --debug to see whether content is empty versus hidden","Switch to a planner model known to return text"],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"match plan_flow().await {\n    Err(e) if e.to_string().contains(\"no user-visible content\") => {\n        plan_flow().await // empty planner output is usually transient\n    }\n    other => other,\n}","preventionTips":["Use a planner model that reliably returns text content","Retry plan requests once on empty-output errors before surfacing them","Keep --debug output available when diagnosing planner replies"],"tags":["planner","llm-response","cli","validation"],"backgroundTag":null,"analyzedSha":"3810898a7447ec3299be72e223d3570a7aabf0ab","analyzedAt":"2026-08-16T10:14:26.282Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}