Development

When the Judge Rejects a Cheap Model: Distinguishing Faults

Antonio Evans10 min read

A clean editorial diagram on white: three vertical lanes labeled Format, Factuality, Instruction.
Key points

Key points

  1. 1Rejections from a cheap judge model come in three distinct kinds: format failures (unparseable, truncated, or schema-breaking output), factuality failures (wrong or unsupported values), and instruction-following failures (a constraint or field the prompt asked for but did not get).
  2. 2Each kind has a different fix, so attributing cause before swapping the model is what keeps you from paying for a bigger model to solve what was actually a parser or prompt bug.
  3. 3The diagnostic loop is: log the raw judge output, diff it against a strict schema, replay a small labeled set with known faults, and tally a confusion matrix by cause.
  4. 4Swap the model only when the same cause repeats across varied prompts; otherwise fix the parser, the prompt, or the validation step first.

Why a rejection is a symptom, not a diagnosis

A rejection is a single bit. Something downstream said no, and every cause looks identical at the call site. Meanwhile the economics of routing push teams toward cheap models for the bulk of traffic, with a cascade that escalates to a stronger model only when the cheap answer fails a check (TrueFoundry on routing). The danger is that a badly attributed failure turns the cascade into a spend multiplier: you pay the cheap model, you pay the escalation, and you learn nothing about why. As one routing overview puts it, frequent fallbacks add latency and can increase total cost because you pay for the first attempt and the fallback (Merge on routing strategies).

So the first discipline is to stop treating "rejection" as a diagnosis. It is a symptom. The attribution step is what converts an opaque failure rate into a list of causes you can act on.

There is a second reason to be strict here. Judges are prompt-sensitive systems, and identical models produce very different results depending on scoring format, criteria, examples, and information order (Galileo on judge techniques). If your judge is rejecting outputs, the judge's own prompt may be a cause, not the model doing the generating. A taxonomy separates those two failure surfaces.

Three buckets cover nearly every cheap-model rejection you will see in a judge or extractor role. Keep them mutually exclusive in your tagging, because overlapping labels destroy the value of the confusion matrix.

BucketWhat it looks likeTypical root causeUsual fix
FormatInvalid JSON, bad escaping, cut off mid-object, extra prose around the payloadNo schema enforcement, low output token cap, prompt that invites commentaryConstrained decoding, stricter schema, higher token budget, parser that strips fences
FactualityA value that is wrong, invented, or not supported by the sourceModel guess-fills gaps, context too thin, task asks for recall it does not haveRequire citations to source spans, abstain option, retrieval improvements
Instruction-followingIgnores a stated constraint, fills the wrong field, answers only part of a multi-part requestAmbiguous or overloaded prompt, too many constraints per callDecompose the prompt, move constraints into the schema, add a checklist eval

A quick example of why the distinction matters. Suppose a cheap model returns a customer's plan tier as "enterprise" when the account record says "pro." That is factuality. If it returns plan_tier: "Enterprise" with a capital letter and your enum only accepts lowercase, that is format. If it returns the right value in a field called tier when the schema says plan_tier, that is instruction-following. Three different bugs, three different owners, and a model swap fixes at most one of them.

The format bucket deserves special weight because structural fidelity is an operational prerequisite: from the consuming system's perspective, a semantically correct output that violates the expected schema is indistinguishable from a wrong answer (Song et al. on structured output control). That paper also found that strict template-driven generation nearly eliminates syntax errors while structural and semantic errors persist, which is a useful warning: a clean parse does not mean the output is correct.

Step one: capture evidence before you parse

You cannot attribute what you did not keep. Most pipelines log the post-parse object, which is exactly where the evidence is destroyed. Log the raw string, the finish reason, the token counts, and the prompt version, and attach request metadata at the call site so the record is joinable later. The minimum useful set is the user, the feature, the deployment, the prompt version, and a run identifier (Braintrust on cost tracking).

A practical logging record looks like this:

{
  "request_id": "req_8f21",
  "prompt_version": "judge_v3_hash_9a2c",
  "model": "cheap-tier",
  "finish_reason": "length",
  "raw_output": "{\"verdict\": \"reject\", \"reason\": \"the claim about refund window is not supported by",
  "input_tokens": 1840,
  "output_tokens": 64,
  "max_output_tokens": 64
}

The finish_reason: "length" with output tokens equal to the cap is an instant format diagnosis: the model was truncated. That one field will explain a large share of your "the cheap model is bad" complaints. Without it, truncation looks exactly like a refusal or a hallucination.

Also record latency, because routing decisions that ignore responsiveness can silently degrade the product even when quality holds. Time to first token is the metric that most affects perceived speed in interactive paths, while end-to-end latency matters when the full response must arrive before the next step (Anyscale on latency metrics). If your cheap judge is slower than the escalation target, you have a latency bug masquerading as a quality problem.

Step two: diff every output against a strict schema

Run every raw output through a validator that fails loudly and specifically. The goal is not a boolean pass or fail but a machine-readable reason. A JSON Schema validator that reports the failing keyword and path turns "unparseable" into "missing required property plan_tier at root" or "value Enterprise does not match enum at /plan_tier."

This is the cheapest step in the whole process and it catches the format bucket almost completely. It also separates escaping problems (a quote inside a string value breaking the payload) from truncation (a payload that ends mid-token) from commentary (prose before or after the object). Each of those has a different fix.

For the escaping and commentary cases, a tolerant extraction layer often resolves the issue without touching the model: strip code fences, find the outermost balanced braces, then validate. If that alone drops your format rejections sharply, you have proven the model was fine and the parser was the fault. That is a successful diagnosis, not a workaround to be embarrassed about. Where available, prefer constrained decoding so the model cannot emit invalid structure in the first place, but do not let a clean parse lull you into skipping the factuality check (Song et al.).

Step three: replay a small labeled set with known faults

The heart of the method is a fixed set of cases where you already know the correct answer and the intended failure mode. A golden dataset is exactly this: a stable set of test cases you run before every meaningful change, so you can tell whether a change helped or hurt (Langfuse on golden datasets). Evaluation datasets can hold inputs alone or inputs with expected outputs, and they pair with an evaluator that either checks properties directly or compares against ground truth (Evidently on test datasets).

Build the set deliberately so each case is designed to elicit one fault:

Case typeInput patternKnown fault it should surface
Clean controlWell-formed request, answer present in contextNone (a rejection here is a judge bug)
Missing fieldRequest omits a value the schema requiresInstruction-following or abstention
Long contextSource document near the context limitFormat (truncation)
Conflicting valuesTwo source spans disagreeFactuality
Multi-constraintThree or four explicit constraints in one promptInstruction-following (partial answer)
Adversarial phrasingQuotes, newlines, unicode in valuesFormat (escaping)

Keep the set small enough to run on every prompt change, large enough that a single flaky case does not move the number. Thirty to fifty well-chosen cases usually beat a thousand random ones for this purpose, because you are not measuring general quality, you are distinguishing causes.

For expected answers, define evaluation criteria as concrete, checkable statements rather than vibes. A worked pattern from an evaluation write-up shows the criteria as a list of yes-or-no questions about coverage, specifics, practical detail, tone, and forbidden content, paired with a dataset of input and expected output pairs (Seya on evaluation criteria). That mirrors the binary-verdict advice from judge tuning: ask "does this response contain any factually incorrect statements, yes or no" rather than "rate accuracy from 0 to 100" (Galileo).

Step four: build the confusion matrix and apply the decision rule

Now tally. For each case, record the designed fault and the observed fault. The matrix tells you whether your judge fails in the way you think it does.

Designed faultObserved formatObserved factualityObserved instructionObserved pass
Clean control10247
Missing field0965
Long context18110
Conflicting values01424
Multi-constraint13115
Adversarial phrasing12008

Read it by column and row together. Here, long context and adversarial phrasing collapse into format: the fix is a token budget and an extraction layer, not a better model. Missing field splits between factuality (the model guess-fills) and instruction (it skips the field), which tells you to add an explicit abstain instruction and a required-field check. The clean-control column is your alarm: two instruction failures on cases that should trivially pass mean the judge prompt itself is over-constrained.

The off-diagonal cells are the interesting ones. A designed factuality case that shows up as format usually means the model started fabricating and then broke the schema trying to fit the fabrication in. Treat that as factuality with a format side effect, because fixing the schema will not remove the invention.

The decision rule itself is simple enough to write on a sticky note. Swap the model only when the same cause repeats across varied prompts. Otherwise:

  • Format dominates and finish reasons show truncation: raise the output cap, add constrained decoding, keep the model.
  • Format dominates and finish reasons look normal: fix the parser or the prompt's output instructions, keep the model.
  • Factuality dominates: the task needs recall or grounding the cheap model does not have on this data. Either improve retrieval and require source spans, or escalate this task class to a stronger model. This is the one bucket where a swap is often the correct answer.
  • Instruction-following dominates: decompose the prompt. One job per call, constraints moved into the schema, a short checklist eval. A bigger model will paper over an overloaded prompt but you will pay for it on every request.

A caution on the swap: automatic selection by price or benchmark is risky when tool behavior, data policy, or quality requirements are strict, and a generic benchmark is a poor guide for a specialized task (Inworld on routing). Your confusion matrix is a better routing signal than any public leaderboard, because it is built on your data and your fault distribution.

Track a small set of routing-health metrics alongside the matrix: fallback rate, cache hit rate, and cost per successful outcome. A routing layer that looks accurate can still be inefficient, and silent drift in these numbers is the usual culprit (MLflow on routing). Cost per successful outcome is the number that actually decides whether your cheap model is cheap, and it is the number the matrix exists to protect.

Worked example: the refund-window extractor

A support team runs a cheap model as an extractor over policy documents. Every extracted claim is tagged with a refund window in days. The rejection rate on the downstream validator is 22 percent and the team is about to move to a frontier model.

Attribution on 200 sampled rejections, run through the steps above:

  1. Raw logs show finish_reason: "length" on 61 of the 200, all on documents over roughly 3,000 input tokens. Format, truncation.
  2. A schema diff on the remaining 139 finds 38 with an enum mismatch ("30 Days" versus 30) and 12 with an unescaped quote inside a reason string. Format, parser and prompt.
  3. Of the 89 that parse, 54 cite a window not present in the source span. Factuality.
  4. The last 35 parse correctly, cite a real span, but miss the secondary constraint ("also report the currency"). Instruction-following.

So format is 111 of 200, factuality 54, instruction 35. The proposed swap would have addressed about a quarter of the problem and left the dominant cause untouched. The fixes: raise the output cap for long documents, coerce enum types in the parser, add a currency field to the schema with an explicit example, and for the 54 factuality cases require the extractor to return the exact source sentence or abstain. Only if factuality stays high after grounding do you escalate that task class, and then you escalate it selectively rather than moving all traffic.

Replaying the labeled set after these fixes is what proves the diagnosis. If format rejections drop to near zero and factuality holds, you saved a model migration. If factuality stays high with grounding in place, you have earned the right to swap, and you can show the evidence.

Be honest about judge reliability throughout. Judges are unstable across scenarios, and rubrics or references help but are not always sufficient (LongJudgeBench). If your confusion matrix has a lot of mass in "observed pass" for cases you designed to fail, the problem may be the judge's rubric, not the model under test. Judges agree with human reviewers often enough to be useful for scoring open-ended text, but the wrong scoring method or rubric makes the scores just as flaky as the model being tested (Confident AI on judges).

When the taxonomy points to a task class that genuinely needs a stronger model, the natural next step is a single gateway that reaches text, image, video, audio, and embedding models through one OpenAI-compatible key with prepaid US dollar pricing, which is what Quanta Inference provides. That lets you escalate one task class without rebuilding each provider integration.

FAQ

FAQ

How many labeled cases do I need before the confusion matrix is trustworthy?

Thirty to fifty deliberately designed cases are enough to distinguish causes, because you are not measuring overall quality. Make each case target one fault, and include a generous block of clean controls. If a single case can flip your conclusion, you need more controls rather than more random samples.

What if a rejection fits two buckets at once?

Assign the primary cause by the first check that fails, then note the secondary cause in a separate field. A hallucinated value that also breaks the schema is factuality with a format side effect, because fixing the schema will not remove the invention. Keeping one primary label per rejection is what keeps the matrix readable.

Can I skip the schema diff if I already use constrained decoding?

No. Constrained decoding addresses syntax, but structural and semantic errors persist even when syntax is nearly perfect (Song et al.). A clean parse means the payload is machine-readable, not that the value is right. You still need the factuality and instruction checks downstream.

How do I know the judge itself is not the problem?

Put clean control cases in your set and watch them. If well-formed requests with the answer present in context are getting rejected, the judge prompt or rubric is over-constrained, not the model under test. Judges are sensitive to prompt structure and scoring format, and binary criteria with verifiable answers give the most reliable signal (Galileo).

When is a model swap clearly the right call?

When factuality failures dominate, repeat across varied prompts, and survive grounding and an abstain option. At that point the task needs recall or reasoning the cheap tier does not provide on your data, and escalation is the honest fix. Format and instruction failures rarely justify a swap on their own, because they are usually fixed for less money in the parser or the prompt.

Sources

Sources

  1. Intelligent LLM Routing: Cost & Quality-Aware Selection
  2. LLM routing: overview, strategies, and tools
  3. Tricks to Improve LLM-as-a-Judge
  4. Empirical Study for Structured Output Control in LLMs for ...
  5. How to track LLM costs (2026): A playbook for per-user, per ...
  6. Understand LLM latency and throughput metrics
  7. Golden dataset evaluation: build and maintain LLM test sets
  8. How to create LLM test datasets with synthetic data
  9. Creating Evaluation Criteria and Datasets for your LLM App
  10. LLM Routing Strategies: Conditional Routing, Failover, and ...
  11. LLM Routing in Production: Four Stages, Mapped to MLflow
  12. Benchmarking LLM-as-a-Judge for Long-Form Output ...
  13. LLM-as-a-Judge Simply Explained: The Complete Guide to ...
About the author

About the author

Antonio Evans
Antonio Evans

Antonio Evans is the founder of Quanta Intelligence and a fractional CTO who builds HIPAA-ready AI systems for health and life-science companies. Before that he was technical co-founder of FriendsEAT for twenty years, CEO of Socialdraft, and a data engineer at IBM. Antonio lives with his dog Santino in Lisbon, Portugal.

All articles