Hmbown/CodeWhale · error

Review max_chars must be positive

Error message

Review max_chars must be positive

What it means

Planning guard in plan_pr_review: the max_chars budget for a review pass must be greater than zero; a zero/negative budget cannot fit any file, so the planner rejects the configuration up front rather than producing a pass plan that covers nothing (#6285: degrading is for oversized files, not for a nonsensical budget).

Solutions

  1. Set review max_chars to a positive value (e.g. >= a few thousand) in config
  2. Fix the caller to clamp: `max_chars.max(MIN_REVIEW_CHARS)` or default when 0
  3. Check the budget computation upstream that yielded 0

Example fix

// before
let max_chars = 0;
plan_pr_review(diff, &view, max_chars, max_passes)?;
// after
let max_chars = 64_000; // or from config, must be > 0
plan_pr_review(diff, &view, max_chars, max_passes)?;
Defensive patterns

Strategy: validation

Validate before calling

if max_chars == 0 { return Err(anyhow!("max_chars must be > 0")); }

Try / catch

match plan_pr_review(...) { Err(e) if e.to_string().contains("max_chars must be positive") => use_default_max_chars(), ... }

Prevention

When it happens

Trigger: Calling plan_pr_review (or the review tool's execute path) with max_chars = 0, typically from config where a budget was computed as 0 (e.g. zero remaining context budget or a misconfigured review.max_chars).

Common situations: Config file setting max_chars: 0; budget arithmetic underflowing/clamping to 0; caller passing a default-constructed usize before computing the real limit.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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

Appendix: source

Thrown at crates/tui/src/tools/review.rs:431

        reason: &'static str,
    },
}

/// Plan PR review passes over `diff`, degrading instead of failing closed
/// (#6285 AC3): files that fit no pass and passes beyond `max_passes` are
/// skipped in diff order and named in `manifest.skipped_files` (AC4). Only a
/// plan that covers nothing still errors.
///
/// Known limitations, beside the behaviour: skips are whole files — a file
/// with one oversized hunk is skipped entirely, never truncated — and files
/// stay in diff order rather than re-sorted by estimated risk.
pub(crate) fn plan_pr_review(
    diff: &str,
    view: &super::review_pr::GhPullRequest,
    max_chars: usize,
    max_passes: usize,
) -> anyhow::Result<PrReviewPlan> {
    anyhow::ensure!(max_chars > 0, "Review max_chars must be positive");
    anyhow::ensure!(
        (1..=MAX_REVIEW_PASSES).contains(&max_passes),
        "Review max_passes must be from 1 to {MAX_REVIEW_PASSES}"
    );
    let patches = pr_file_patches(diff);
    anyhow::ensure!(
        patches.len() == view.changed_files && !patches.is_empty(),
        "Complete PR review plan found {} file patches; expected {}",
        patches.len(),
        view.changed_files
    );

    // A whole file stays together whenever it fits. An oversized text file
    // splits only at complete hunk boundaries, with the full file header
    // replayed into every part so each part stays a self-describing patch;
    // no line is elided, shortened or reordered. Sizes use the model
    // representation, so a binary payload already omitted there can never
    // drive a split.

View on GitHub (pinned to 73e0f67d83)