When Bundle Validation Passes but Terminology Fails

Structural Bundle validation and terminology validation answer different questions. A payload that passes the first and fails the second is a common outcome in mature integrations, and treating the two as one layer is where downstream data-quality programs lose ground. The clean framing is that structural validation confirms the shape of the payload, and terminology validation confirms the meaning carried inside it.

The gap between the two is not a bug in the tooling. It is the tooling drawing a specific line. Related patterns sit under more on FHIR data exchange patterns for the wider surface.

What Each Layer Actually Checks

Structural validation walks the resources in a Bundle and confirms that every element exists in the base spec or a loaded profile, that cardinality is respected, that primitive types match, and that internal references resolve. It runs offline, produces deterministic output, and answers cleanly on a single Bundle.

Terminology validation walks each Coding and asks whether the code exists in the code system, whether it is active, and whether it belongs to the value set the profile binds. It requires an external terminology server or a loaded value-set snapshot. It runs slower, and it can return partial answers on very large value sets. A pass through the site's Bundle JSON check covers the structural side; the terminology side needs a separate step.

Where the Gap Shows Up in Practice

Three cases account for most reported gaps:

  1. Legacy LOINC codes — the code is still valid in LOINC but was deprecated in the profile's value set version.
  2. SNOMED CT jurisdiction — a code that is valid in one national extension is not present in the receiver's edition.
  3. Locally minted codes — a code from a house code system that was accepted upstream but is not bound in any published value set.

Each case passes structural validation cleanly. The Coding.system and Coding.code are populated, the reference to the value set exists, and no cardinality rule fires. The terminology check is the one that surfaces the mismatch.

Reading the Combined Report

A validator that runs both layers should emit issues that name the layer. Reports that only surface diagnostic strings without a layer tag force the stakeholder to reconstruct the grouping every time. For the reader-side habit, reading FHIR validation output as a non-developer stakeholder covers the questions to ask the report.

The practical rule is to fix structural first, then rerun, then read terminology. Fixing them in the reverse order leaves the reader chasing symptoms of misshapen payloads.

Governance Implications

A data-quality program that reports on "validation" without naming the layer inherits ambiguity in every KPI. Programs that split the two layers into distinct metrics gain a clean signal on where fix effort should land: structural failures usually mean a generator bug, terminology failures usually mean a value-set update. For the audit-trail integration, audit trails grounded in structural Bundle validation covers the retention model that keeps both layers inspectable.

The two-layer framing is a small language change with a large operational payoff. Naming the split is what turns a mixed report into a work plan.

Botanical-sketch diagram of a two-tier validation grid with a hand-drawn structural pass row on top in muted greens and a terminology fail row below in muted red with callouts pointing at deprecated codes

Sources

  • HL7 FHIR core specification - HL7 FHIR core specification, Validation section: canonical explanation of structural versus terminology validation split