Hmbown/CodeWhale · error · anyhow::Error

Model response incomplete: provider stop reason

Error message

Model response incomplete: provider stop reason `{}`; the JSON receipt records success=false.

What it means

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.

Solutions

  1. Read the receipt's stop_reason/usage fields to confirm the truncation cause.
  2. Raise the max output tokens or reduce task size, then re-run.
  3. 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.

Example fix

// before (consumer)
const receipt = JSON.parse(out); use(receipt.output);
// after
const receipt = JSON.parse(out);
if (!receipt.success) throw new Error(`incomplete: ${receipt.stop_reason}`);
Defensive patterns

Strategy: type-guard

Validate before calling

const receipt = JSON.parse(stdout);
if (receipt.success !== true || isIncompleteStopReason(receipt.stop_reason)) {
  throw new Error(`incomplete generation: ${receipt.stop_reason}`);
}

Type guard

function isCompleteReceipt(r) {
  return typeof r === 'object' && r !== null && r.success === true &&
         !['max_tokens', 'length'].includes(String(r.stop_reason).toLowerCase());
}

Try / catch

try {
  const out = exec('codewhale ask --output-format json ...');
  const receipt = JSON.parse(out);
  if (!isCompleteReceipt(receipt)) throw new Error('incomplete');
} catch (e) { /* retry with larger budget */ }

Prevention

When it happens

Trigger: 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.

Common situations: CI jobs parsing `--output-format json` output hitting truncated generations; scripts that must fail loudly when the model answer is cut off.

Related errors


AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22). Data as JSON: /api/errors/5a84549c2ed2594a. Report an issue: GitHub.

Appendix: source

Thrown at crates/tui/src/lib.rs:11856

    let usage = response.usage.clone();
    let mut output = String::new();
    for block in response.content {
        if let ContentBlock::Text { text, .. } = block {
            output.push_str(&text);
        }
    }
    println!(
        "{}",
        serde_json::to_string_pretty(&one_shot_exec_json_receipt(
            provider,
            model,
            output,
            stop_reason.clone(),
            usage,
        ))?
    );
    if is_incomplete_stop_reason(stop_reason.as_deref()) {
        anyhow::bail!(
            "Model response incomplete: provider stop reason `{}`; the JSON receipt records success=false.",
            stop_reason_detail(stop_reason.as_deref())
        );
    }
    Ok(())
}

fn one_shot_exec_json_receipt(
    provider: String,
    model: String,
    output: String,
    stop_reason: Option<String>,
    usage: codewhale_models::Usage,
) -> serde_json::Value {
    let incomplete = codewhale_models::is_incomplete_stop_reason(stop_reason.as_deref());
    let error = incomplete.then(|| {
        format!(
            "Model response incomplete: provider stop reason `{}`.",

View on GitHub (pinned to 73e0f67d83)