Hmbown/CodeWhale · error · anyhow::Error

continual harness {field} must be {min}..={max} characters

Error message

continual harness {field} must be {min}..={max} characters

What it means

Thrown by validate_refinement via normalize_bounded when a refinement field, after trimming, falls outside its character bounds. Limits: title 1..=96, content 1..=1600, evidence 16..=1200 (MAX_*_CHARS constants). Length is counted in Unicode scalar values (chars().count()), and the error names the offending field. Note evidence has a minimum of 16, so a short evidence string like "test" fails even though it is non-empty.

Source

Thrown at crates/tui/src/continual_harness.rs:348

            state_path.display()
        )
    })?;
    operation()
}

fn validate_refinement(mut refinement: HarnessRefinement) -> Result<HarnessRefinement> {
    refinement.title = normalize_bounded("title", refinement.title, MAX_TITLE_CHARS, 1)?;
    refinement.content = normalize_bounded("content", refinement.content, MAX_CONTENT_CHARS, 1)?;
    refinement.evidence =
        normalize_bounded("evidence", refinement.evidence, MAX_EVIDENCE_CHARS, 16)?;
    Ok(refinement)
}

fn normalize_bounded(field: &str, value: String, max: usize, min: usize) -> Result<String> {
    let value = value.trim().to_string();
    let len = value.chars().count();
    if len < min || len > max {
        bail!("continual harness {field} must be {min}..={max} characters");
    }
    Ok(value)
}

fn truncate_chars(value: &str, max: usize) -> String {
    let mut chars = value.chars();
    let head: String = chars.by_ref().take(max).collect();
    if chars.next().is_some() {
        format!("{head}…")
    } else {
        head
    }
}

fn escape_for_prompt(value: &str) -> String {
    value
        .replace('&', "&amp;")
        .replace('<', "&lt;")

View on GitHub (pinned to 0c42157ee5)

Solutions

  1. Trim or expand the named field to within bounds: title 1-96, content 1-1600, evidence 16-1200 characters
  2. Write evidence of at least 16 characters describing where the refinement was verified
  3. Count characters (not bytes) when pre-measuring CJK content

Example fix

// before
let refinement = HarnessRefinement {
    kind: HarnessEntryKind::PromptNote,
    title: "note".into(),
    content: "Use release builds for timing.".into(),
    evidence: "test".into(),
};

// after
let refinement = HarnessRefinement {
    kind: HarnessEntryKind::PromptNote,
    title: "note".into(),
    content: "Use release builds for timing.".into(),
    evidence: "Verified on the dxg repo: release build reproduced the 2x speedup.".into(),
};
Defensive patterns

Strategy: validation

Validate before calling

fn refinement_is_valid(r: &HarnessRefinement) -> bool {
    let in_bounds = |v: &str, min: usize, max: usize| {
        let n = v.trim().chars().count();
        (min..=max).contains(&n)
    };
    in_bounds(&r.title, 1, 96)
        && in_bounds(&r.content, 1, 1600)
        && in_bounds(&r.evidence, 16, 1200)
}

Prevention

When it happens

Trigger: Calling refine with an empty title/content, a one-word evidence string under 16 chars, or fields over their maxima (e.g. a 2000-char content).

Common situations: The model submitting a refinement with terse evidence; multi-byte text (CJK) where byte length and char count diverge; pasting long briefs into content.

Related errors


AI-assisted analysis of Hmbown/CodeWhale@0c42157ee5 (2026-08-20). Data as JSON: /api/errors/a4e1f0045a74464b. Report an issue: GitHub.