Debugging Evaluation Failures in i-have-adhd: A Complete Troubleshooting Guide
The i-have-adhd repository uses a three-stage validation pipeline in scripts/run_evals.py to catch evaluation failures before running LLM calls, with descriptive error messages pointing to exact data problems in case files or score rows.
When working with the evaluation harness in ayghri/i-have-adhd, debugging evaluation failures requires understanding how the validation pipeline isolates data errors from runtime execution issues. The harness validates case catalogs, score rows, and condition pairings before any LLM calls are made, ensuring you get actionable error messages instead of cryptic runtime failures.
The Three-Stage Validation Pipeline
The debugging process for evaluation failures centers on three validation stages implemented in run_evals.py. Each stage raises specific exceptions that identify exactly what's wrong with your evaluation data.
Stage 1: Case Catalog Validation
The validate_cases function (lines 59-79 in scripts/run_evals.py) checks every entry in evals/cases.jsonl for structural integrity.
This validator ensures:
- All required fields (
id,category,prompt,risk,criteria) are present - Case IDs are unique across the catalog
- The
riskfield contains onlylow,medium, orhigh - The
criterialist is non-empty
Typical failure messages include Case 3: missing fields: prompt, risk or Duplicate case id: direct-answer.
python -m scripts.run_evals validate --cases evals/cases.jsonl
A successful validation prints "Evaluation cases are valid."; failures list every problem found with row references.
Stage 2: Score Row Validation
The _validate_score function (lines 82-95) validates submitted scoring data against the expected schema.
Each score row must contain:
- All five metrics:
correctness,autonomy,actionability,safety,concision(values 1-5) - A
conditionfield with valuebaseline,candidate, orcomparator - Boolean
blockerflag - Optional
notesstring
Failures produce messages like Score row 7: missing fields: autonomy or must be between 1 and 5 for correctness.
Stage 3: Pairing and Completeness Verification
The _check_pairing function (lines 101-128) ensures fair comparison across experimental conditions.
This critical check verifies that:
- Every condition was judged on identical case-trial pairs
- No duplicate score rows exist for the same case-trial-condition combination
- The evaluation matrix is complete
Common failure: candidate was not judged on the same rows as baseline: missing direct-answer/trial 2; unmatched refusal/trial 1
Step-by-Step Debugging Workflow
Follow this sequence to resolve evaluation failures efficiently.
Step 1: Run the Validator in Isolation
Always start with the validate sub-command to catch data errors before consuming API budget:
python -m scripts.run_evals validate
Step 2: Parse the Exception Traceback
The harness raises ValueError with descriptive messages. The traceback points to the exact line in run_evals.py, and the message includes the offending row number or case ID.
For example, a duplicate row error:
ValueError: Score row 12: duplicate score rows for direct-answer/trial 1
Step 3: Fix the Source Data
| Error Type | Fix Location | Action |
|---|---|---|
| Missing/duplicate case IDs | evals/cases.jsonl |
Add required fields; ensure ID uniqueness |
| Invalid risk values | evals/cases.jsonl |
Use only low, medium, high |
| Malformed score rows | Your scores JSONL file | Ensure all five metrics present, range 1-5 |
| Pairing mismatch | Your scores JSONL file | Align case-trial pairs across all conditions |
Step 4: Regenerate the Run Matrix (If Needed)
For pairing failures, use the plan command to see the expected evaluation structure:
python -m scripts.run_evals plan \
--cases evals/cases.jsonl \
--trials 2 \
--include-comparator
This outputs the complete matrix of {case_id, trial, condition} rows that your scoring data must cover.
Step 5: Verify Budget Constraints
If evaluation stops with "Budget exhausted", check:
- The
--budget-usdparameter value - That your runner correctly reports
cost_usdin its output
The harness aborts after the call that exceeds budget, showing the final "Reported cost:" line for diagnosis.
Using the Test Suite to Understand Failures
The test file tests/test_run_evals.py deliberately triggers each validation error. Run it to see expected failure patterns:
pytest tests/test_run_evals.py -q
Each test case demonstrates the exact message format you'll encounter in production, making it a reliable reference for interpreting real failures.
Key Files for Debugging Evaluation Failures
| File | Purpose | Critical Functions |
|---|---|---|
scripts/run_evals.py |
Main evaluation driver | validate_cases, _validate_score, _check_pairing |
tests/test_run_evals.py |
Validation test suite | Exercises all error paths |
evals/cases.jsonl |
Case catalog schema | Validated by validate_cases (L59-79) |
evals/runners.example.json |
LLM runner configuration | Referenced by run sub-command |
Summary
- Running
validateisolates data errors before expensive LLM calls - Three validation stages check cases, scores, and pairings with specific error messages
- Tracebacks include row numbers and case IDs for precise debugging
- The
plancommand generates the expected evaluation matrix for alignment checks - Tests in
test_run_evals.pydemonstrate all failure modes and expected fixes
Frequently Asked Questions
What does "unsupported condition" mean in an evaluation failure?
This error from _validate_score indicates the condition field in your score row contains a value other than baseline, candidate, or comparator. Check your scoring data and use only these three valid condition labels.
How do I fix "candidate was not judged on the same rows as baseline"?
This _check_pairing failure means your experimental conditions have mismatched case-trial coverage. Use python -m scripts.run_evals plan to generate the complete matrix, then ensure every condition has scores for exactly those case-trial pairs—no more, no less.
Why does validation pass but the run command still fails?
The validate sub-command only checks evals/cases.jsonl. Runtime failures typically involve: (1) your runner configuration in evals/runners.example.json, (2) missing or malformed score files for the score sub-command, or (3) pairing validation that only runs when processing actual scores. Run validate on your scores file explicitly if using manual scoring.
Can I debug evaluation failures without running LLM calls?
Yes—use the validate and plan sub-commands, plus the test suite. These exercise the full validation pipeline without invoking any LLM backends or consuming API budget.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →