{"record":{"id":"5a84549c2ed2594a","repo":"Hmbown/CodeWhale","slug":"model-response-incomplete-provider-stop-reason-5a8454","errorCode":null,"errorMessage":"Model response incomplete: provider stop reason `{}`; the JSON receipt records success=false.","messagePattern":"Model response incomplete: provider stop reason `(.+?)`; the JSON receipt records success=false\\.","errorType":"error_code","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/tui/src/lib.rs","lineNumber":11856,"sourceCode":"    let usage = response.usage.clone();\n    let mut output = String::new();\n    for block in response.content {\n        if let ContentBlock::Text { text, .. } = block {\n            output.push_str(&text);\n        }\n    }\n    println!(\n        \"{}\",\n        serde_json::to_string_pretty(&one_shot_exec_json_receipt(\n            provider,\n            model,\n            output,\n            stop_reason.clone(),\n            usage,\n        ))?\n    );\n    if is_incomplete_stop_reason(stop_reason.as_deref()) {\n        anyhow::bail!(\n            \"Model response incomplete: provider stop reason `{}`; the JSON receipt records success=false.\",\n            stop_reason_detail(stop_reason.as_deref())\n        );\n    }\n    Ok(())\n}\n\nfn one_shot_exec_json_receipt(\n    provider: String,\n    model: String,\n    output: String,\n    stop_reason: Option<String>,\n    usage: codewhale_models::Usage,\n) -> serde_json::Value {\n    let incomplete = codewhale_models::is_incomplete_stop_reason(stop_reason.as_deref());\n    let error = incomplete.then(|| {\n        format!(\n            \"Model response incomplete: provider stop reason `{}`.\",","sourceCodeStart":11838,"sourceCodeEnd":11874,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/73e0f67d83c59909b571efdfc88c4bc28c309cb1/crates/tui/src/lib.rs#L11838-L11874","documentation":"In the JSON output path, the receipt is emitted first, then `is_incomplete_stop_reason` is checked; an incomplete provider stop reason makes the command bail with a message noting the JSON receipt already records success=false, so machine consumers see a consistent failed exit.","triggerScenarios":"A one-shot model request run with JSON output finishes with an incomplete stop reason (max tokens/length), after the receipt containing `success=false` has been printed.","commonSituations":"CI jobs parsing `--output-format json` output hitting truncated generations; scripts that must fail loudly when the model answer is cut off.","solutions":["Read the receipt's stop_reason/usage fields to confirm the truncation cause.","Raise the max output tokens or reduce task size, then re-run.","In the consuming script, key off the non-zero exit and the receipt's success=false instead of trusting the partial JSON payload as complete."],"exampleFix":"// before (consumer)\nconst receipt = JSON.parse(out); use(receipt.output);\n// after\nconst receipt = JSON.parse(out);\nif (!receipt.success) throw new Error(`incomplete: ${receipt.stop_reason}`);","handlingStrategy":"type-guard","validationCode":"const receipt = JSON.parse(stdout);\nif (receipt.success !== true || isIncompleteStopReason(receipt.stop_reason)) {\n  throw new Error(`incomplete generation: ${receipt.stop_reason}`);\n}\n","typeGuard":"function isCompleteReceipt(r) {\n  return typeof r === 'object' && r !== null && r.success === true &&\n         !['max_tokens', 'length'].includes(String(r.stop_reason).toLowerCase());\n}\n","tryCatchPattern":"try {\n  const out = exec('codewhale ask --output-format json ...');\n  const receipt = JSON.parse(out);\n  if (!isCompleteReceipt(receipt)) throw new Error('incomplete');\n} catch (e) { /* retry with larger budget */ }\n","preventionTips":["Always check the receipt's success field, not just process output presence.","Budget max output tokens for the largest expected response.","Fail loudly in consumers on success=false rather than parsing partial payloads."],"tags":["model","stop-reason","json","truncation","cli"],"backgroundTag":"unexpected-response-shape","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"}