Est.
Data QualityLong read

Cross-Field Consistency Checks for Invoice Validation

Schema validation catches syntax errors, not the cross-field contradictions that break invoices.

· 10 min read · Updated
Cover illustration for “Cross-Field Consistency Checks for Invoice Validation”
Data Quality · September 6, 2026 · 10 min read · 2,144 words

Schema validation answers a narrow question: is this field the right type, in the right format, inside its declared bounds? That question is syntactic. Whether an invoice is actually correct is a different, semantic question, and schema validators were never built to answer it. A 2026 analysis of Instructor structured outputs shows how wide that gap can get in practice: a customer-extraction agent running at a high schema-pass rate still returns an Invoice.total that disagrees with sum(line_items) on roughly 4 percent of orders, and every case marked severity: 'urgent' carries escalation_required: False right alongside it. Every Pydantic check passes on every one of those records. Every one of those values is wrong in a way that costs money or breaks a workflow.

The same analysis makes the point with a single object: Customer(id=2147483647, age=204, signup_date=date(1812,4,19), email="a@b.com", tier="enterprise"). Schema-pass rate on that record is perfect. Four of its five fields are wrong. An age of 204 and a signup date from 1812 both satisfy "integer" and "date" constraints without blinking, because a type checker has no concept of what a plausible age or a plausible signup year looks like. It checks the shape of the box, not what's inside it.

Invoices are a particularly unforgiving place for this gap, because an invoice is a system of constraints rather than a collection of independent facts. The total is derived from the line items. The due date is derived from the issue date and the payment terms. The tax amount is derived from the net amount and the tax rate. None of these fields stand alone, and a validator that checks each one in isolation can wave through a document where every individual number looks fine and the relationships between them are broken. Invoice validation guides from 2025 and 2026 consistently describe validation as the checkpoint meant to enforce the business rules schema alone cannot express: contracted pricing, correct tax treatment, PO alignment, proper documentation. That's the job schema validation was never assigned, and it's the job the rest of this piece is about.

The three failure shapes that pass every per-field check

Cross-field invoice errors that defeat schema validation fall into three structurally distinct shapes. Naming them precisely is the first step toward catching them systematically, because each shape calls for a different kind of check, and a validation layer that only looks for one of them will miss the other two.

The first shape is arithmetic disagreement: a derived field disagrees with the fields that determine it. The canonical example comes from the Instructor evaluation analysis: an invoice with total: 199.99 and line_items: [{price: 49.99}, {price: 49.99}]. The floats are floats. The list is a list. Every field-level constraint passes, and the invoice is still wrong by a hundred dollars. On a real invoice, this shape appears as net plus tax not equaling gross, unit price times quantity not equaling the line total, or the sum of line totals not equaling the subtotal. It's the easiest shape to catch with a deterministic rule, and the most expensive shape to let slip through, because it maps directly onto overpayment or underpayment.

The second shape is temporal inversion: a date-ordering rule breaks. A due date lands before the issue date. A service period ends before it starts. These inversions are often OCR artifacts: a model extracts a date in one format from one vendor and a different format from another, both look like valid dates, and the downstream database breaks silently when the comparison is finally made. That's a format problem masquerading as a logic problem, and catching it requires normalizing every date to one canonical format before any ordering check runs, something the engineering section on temporal checks covers in detail.

The third shape is logical-implication conflict: a flag, status, or category contradicts another field it logically implies or depends on. An example from the structured-output evaluation analysis: status == 'shipped' with tracking_number set to None, and severity: 'urgent' paired with escalation_required: False. On an invoice, the same shape appears as a tax_exempt: true flag sitting on a line that carries a non-zero tax amount, a currency: 'EUR' field attached to a supplier registered in a country that doesn't use EUR, or a payment_method: 'credit' field on an invoice to a counterparty the vendor master marks cash-only. This is the hardest shape to catch because the rule being broken was never written into the schema. It lives in business logic and domain knowledge that someone has to encode separately.

OCR accuracy, IDP extraction, and the gap between them

Cross-field inconsistencies are not extraction errors; they can appear in documents where every field was extracted correctly. Improving OCR accuracy does not prevent them. One analysis of the problem puts the distinction directly: OCR is an excellent reader, and it is in no way an analyst. A state-of-the-art OCR engine can post high accuracy on raw extraction, and extraction accuracy still measures something entirely different from verification reliability.

That same analysis lists what OCR cannot do no matter how accurate it gets: compare values across fields or across documents, weigh a date against a business rule (a certificate dated months ago may fail a lender's recency requirement even though the date itself was extracted perfectly), judge whether a revenue figure makes a financing amount plausible, or check two separately extracted dates for coherence with each other. Each of those is a relationship between pieces of information, and OCR has no mechanism for reasoning about relationships. It reads text.

Intelligent document processing moves the bar further by adding classification and structured extraction on top of OCR, and it can apply consistency rules that stay inside a single document, like confirming the invoice total matches the sum of the line items. The capability table behind that same analysis draws the boundary explicitly, placing cross-document EIN matching, business-rule checks like comparing a financed amount against annual revenue, and external registry verification outside what standard IDP handles. Services like Invofox, a production-grade document parsing API that converts PDFs and images into validated, structured JSON with a per-field accuracy SLA, sit at the extraction layer rather than the verification layer, their job is to surface the field values that consistency checks then reason across. Across a large corpus of documents processed by CheckFile in the second half of 2025, 14.2 percent contained at least one detectable discrepancy between the invoiced amount and the contractual amount, inconsistencies invisible to OCR or standard IDP and caught systematically through cross-document validation.

None of this is a knock on OCR or IDP. Each layer does the job it was built for. No extraction layer, however accurate, was designed to enforce the kind of inter-field business rule that catches an arithmetic error or a backdated due date. Adding a better extraction model is not the same project as adding a consistency layer, and the two have to run together rather than stand in for each other.

LLM-based extraction adds its own wrinkle on top of this. A model extracts a field with the same confident tone whether it found a clearly labeled value or inferred something plausible from surrounding context, so a reliable extraction and a reasonable guess look identical without a downstream check to tell them apart.

Arithmetic checks: the deterministic assertions every invoice pipeline must run

Arithmetic consistency checks run on pure math, need no model call, and cost no tokens, which makes them the natural first gate in any layered validation architecture. The only reason to skip them is not knowing they belong there.

The sum of line totals equals the subtotal. The subtotal times the tax rate equals the tax amount, for each applicable tax line. The subtotal plus tax plus freight plus other charges equals the invoice total. And where partial payment records exist, the sum of those payments stays at or below the invoice total.

These checks belong early in the pipeline, not late. The Instructor evaluation analysis recommends a cheapest-first layering principle: run schema validation and cross-field checks at parse time, for free, then run deterministic post-parse assertions, and only after that send the remaining rows to per-field LLM judges, since judge calls are the expensive line item on the token bill. Arithmetic assertions should fire before an invoice is posted to the ERP or scheduled for payment, catching the error while the money can still be stopped.

Two implementation details decide whether these checks work in production or generate noise that gets ignored. The first is floating-point arithmetic: 0.1 plus 0.2 does not equal 0.3 under IEEE 754. Any check comparing float fields has to cast both sides to a fixed-decimal representation, such as Python's Decimal type with a defined precision, before the comparison runs, or the check will throw false positives on invoices that are actually correct.

The second is tolerance. Some invoicing systems round at each line rather than rounding once at the total, which produces legitimate discrepancies of a penny or two that have nothing to do with a real error. A well-built check separates a rounding-tolerance miss from a substantive arithmetic error by flagging anything outside a configurable epsilon, such as plus or minus 0.05, instead of demanding strict equality.

Temporal checks: normalization before assertion

Temporal checks tend to fail quietly in production, and the logic behind the assertion is rarely the reason. Date values arrive in inconsistent formats, and comparing them before that inconsistency is resolved produces unreliable results no matter how sound the underlying rule is.

Every date field needs to be cast to one canonical representation (ISO 8601, written YYYY-MM-DD) under a single, deterministic normalization policy before any ordering assertion runs. Without that step, whether an ambiguous date string passes or fails depends on which parser happens to touch it first. Silent format drift is one of the more persistent failure modes in production systems: an LLM might extract one vendor's date in one format and another vendor's date in a different format, both look like valid dates, both are technically correct on their own, and the downstream database breaks silently, becoming visible only when someone files a support ticket about bad data.

The issue date must not come after the due date. The service period's start must not come after its end. The issue date must not come after the end of the service period it covers, in most accounts-payable contexts. The due date, derived by adding the stated payment terms to the issue date, has to match the invoice's stated due date within a small tolerance for weekends and holidays. And the issue date needs to sit at or after a configurable earliest-plausible-date boundary, which catches date-parsing errors like a signup date of 1812-04-19.

The CheckFile cross-document validation analysis cites a concrete case that shows why this matters beyond simple ordering: a power of attorney dated two weeks after the contract it was meant to authorize. The extraction itself was accurate. The inconsistency was a logic problem invisible to OCR. The payment-terms derivation check carries similar weight, because when the stated due date doesn't match the issue date plus the stated payment terms, exactly one of three things is true: the terms were extracted wrong, the dates were extracted wrong, or the invoice really was issued on non-standard terms that need a human to look at it. Teams that skip normalization before running these assertions end up with checks that fire on correctly formatted invoices as often as they fire on real problems, and that noise erodes trust in the whole validation layer faster than any single missed error would.

Logical-implication checks: encoding business rules as first-class constraints

The third failure shape, logical-implication conflict, is the hardest of the three to catch because the rule it breaks was never written into the schema in the first place. An arithmetic check works off pure math. A temporal check works off date ordering. A logical-implication check works off a business rule that someone has to state explicitly and encode as a constraint, the same way a tax-exempt flag implies a zero tax amount, or a currency code implies a supplier registered in a country that uses that currency.

Schema validation looks most convincing and is least informative here, because every field involved can be perfectly well-typed. A tax_exempt boolean set to true and a tax_amount field holding a non-zero decimal are each, on their own, exactly the kind of value a Pydantic model expects. The problem only exists in the relationship between them, and that relationship has to be written down as its own rule, separate from and in addition to the type system. Building that rule set means treating each business policy, contracted pricing, tax treatment, PO alignment, documentation requirements, as a first-class assertion sitting alongside the arithmetic and temporal checks, encoded in the system itself rather than left as a note for a human reviewer to catch later.

Sources

  1. invoicedataextraction.com
  2. checkfile.ai
  3. arxiv.org
  4. parseur.com
Filed underData Quality

More in Data Quality