{"record":{"id":"d58823e015694443","repo":"Hmbown/CodeWhale","slug":"review-pass-expected-did-not-return-valid-structured-json","errorCode":null,"errorMessage":"Review pass {expected}/{} did not return valid structured JSON; the partial review was not accepted or posted.","messagePattern":"Review pass (.+?)/(.+?) did not return valid structured JSON; the partial review was not accepted or posted\\.","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/tui/src/tools/review.rs","lineNumber":710,"sourceCode":"\nimpl PrReviewAccumulator {\n    pub(crate) fn new(plan: &PrReviewPlan) -> Self {\n        Self {\n            manifest: plan.manifest.clone(),\n            outputs: Vec::new(),\n            raw_outputs: Vec::new(),\n        }\n    }\n\n    pub(crate) fn accept(&mut self, pass: &PrReviewPass, raw: String) -> anyhow::Result<()> {\n        let expected = self.outputs.len() + 1;\n        anyhow::ensure!(\n            pass.manifest.number == expected\n                && self.manifest.passes.get(expected - 1) == Some(&pass.manifest),\n            \"Review pass arrived out of order or does not match the immutable manifest; expected pass {expected}\"\n        );\n        let output = ReviewOutput::from_structured_str(&raw).ok_or_else(|| {\n            anyhow::anyhow!(\n                \"Review pass {expected}/{} did not return valid structured JSON; the partial review was not accepted or posted.\",\n                self.manifest.passes.len()\n            )\n        })?;\n        self.outputs.push(output);\n        self.raw_outputs.push(raw);\n        Ok(())\n    }\n\n    pub(crate) fn finish(\n        self,\n        complete_diff: &str,\n    ) -> anyhow::Result<(ReviewOutput, String, ReviewReceiptCoverage)> {\n        anyhow::ensure!(\n            self.outputs.len() == self.manifest.passes.len(),\n            \"Only {}/{} review passes completed; the partial review was not accepted or posted.\",\n            self.outputs.len(),\n            self.manifest.passes.len()","sourceCodeStart":692,"sourceCodeEnd":728,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/73e0f67d83c59909b571efdfc88c4bc28c309cb1/crates/tui/src/tools/review.rs#L692-L728","documentation":"A review pass was accepted in order but its raw output failed to parse as valid structured JSON (ReviewOutput::from_structured_str returned None). The accumulator rejects the whole partial review so nothing incomplete is posted.","triggerScenarios":"Model returned prose or truncated JSON instead of the required structured format for pass N; response cut off by max_tokens; JSON wrapped in markdown fences or with stray text the parser does not strip.","commonSituations":"Pass prompt too large so the model truncates; model ignoring the output schema on later passes; parser version stricter than what an older model emits.","solutions":["Re-run the failing pass and parse again (transient truncation is common)","Increase the pass output token limit or shrink the pass's diff chunk via smaller max_chars","Verify the prompt includes the exact structured-JSON schema instructions","Strip code fences/leading text, or extend from_structured_str to tolerate them"],"exampleFix":"// before\nlet raw = model.complete(pass_prompt).await?;\nacc.accept(&pass.manifest, raw)?;\n// after\nlet mut raw = model.complete(pass_prompt).await?;\nif !ReviewOutput::parses(&raw) { raw = model.complete(pass_prompt).await?; } // retry once\nacc.accept(&pass.manifest, raw)?;","handlingStrategy":"try-catch","validationCode":"if !ReviewOutput::parses(&raw) { /* retry the pass before accepting */ }","typeGuard":null,"tryCatchPattern":"match acc.accept(&pass.manifest, raw) { Err(e) if e.to_string().contains(\"valid structured JSON\") => retry_pass(pass).await, ... }","preventionTips":["Include the exact structured-JSON schema in every pass prompt","Set output token limits high enough to avoid truncated JSON","Strip markdown fences before parsing; retry a pass once on parse failure"],"tags":["review","json","model-output"],"backgroundTag":"invalid-json-response","analyzedSha":"73e0f67d83c59909b571efdfc88c4bc28c309cb1","analyzedAt":"2026-09-22T01:30:00.501Z","contentChangedAt":"2026-09-22T01:30:00.501Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}