{"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":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/tui/src/lib.rs","lineNumber":10101,"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: crate::models::Usage,\n) -> serde_json::Value {\n    let incomplete = crate::models::is_incomplete_stop_reason(stop_reason.as_deref());\n    let error = incomplete.then(|| {\n        format!(\n            \"Model response incomplete: provider stop reason `{}`.\",","sourceCodeStart":10083,"sourceCodeEnd":10119,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/8880682c63083a91624de936797efa3ce9e498fd/crates/tui/src/lib.rs#L10083-L10119","documentation":"JSON-mode variant of the incomplete-stop-reason guard: the one-shot run first prints a JSON receipt (which records success=false and the stop reason), then bails with this message for the same incomplete reasons: output limits (length, max_tokens, max_output_tokens), content_filter, model_context_window_exceeded, or 'incomplete:'-prefixed Responses API statuses.","triggerScenarios":"One-shot runs with JSON output enabled where the answer exceeds the output token limit, the context window is exceeded, or a content filter stops generation; the receipt on stdout is valid JSON, but the process exit code is non-zero.","commonSituations":"Automation parsing receipts hitting silent truncation, structured pipelines assuming receipt presence implies success, low token defaults in CI-invoked one-shot runs.","solutions":["Read the receipt's stop_reason field and fix the named cause (raise the output budget, shrink input, or change model)","Check the receipt's success flag rather than assuming printed JSON means the command worked","Split oversized tasks into smaller one-shot calls so answers fit the budget","For content_filter stops, adjust the prompt or policy instead of retrying"],"exampleFix":"# before: receipt printed, exit code ignored\nout=$(sandbox exec --json 'summarize this 50k-line log')\n# after: branch on the receipt, then the exit code\nout=$(sandbox exec --json 'summarize this 50k-line log') || echo \"incomplete: $out\" >&2","handlingStrategy":"type-guard","validationCode":null,"typeGuard":"// The receipt is structured output: branch on its fields, not on stderr text\n#[derive(serde::Deserialize)]\nstruct OneShotReceipt {\n    success: bool,\n    stop_reason: Option<String>,\n}\nfn failed_by_stop_reason(raw: &str) -> Option<String> {\n    serde_json::from_str::<OneShotReceipt>(raw)\n        .ok()\n        .filter(|r| !r.success)\n        .and_then(|r| r.stop_reason)\n}","tryCatchPattern":"// Script pattern: parse the receipt from stdout, then honor the exit code\nconst out = runOneShotJson(prompt);\nconst receipt = JSON.parse(out);\nif (receipt.success === false && /length|max_tokens|content_filter/.test(receipt.stop_reason ?? '')) {\n    return retryWithHigherBudget(prompt);\n}","preventionTips":["Always parse the JSON receipt; printed JSON does not imply success","Size output budgets to the task before one-shot runs","Split oversized tasks so answers fit the configured limit","Send content_filter receipts to prompt review instead of retrying"],"tags":["llm","provider","stop-reason","one-shot","json","truncation"],"backgroundTag":null,"analyzedSha":"8880682c63083a91624de936797efa3ce9e498fd","analyzedAt":"2026-08-16T11:31:27.956Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}