Understanding FHIR Validator Cardinality and Slicing Errors
Hl7 Tools

Understanding FHIR Validator Cardinality and Slicing Errors

The Two Errors Every FHIR Implementer Eventually Meets

You convert a record, validate it, and the report comes back red with messages like minimum required = 1, but only found 0 or This element does not match any known slice. These are cardinality and slicing errors — the two most common, and most misunderstood, failures in FHIR conformance. They are not bugs in your data so much as a mismatch between what you sent and what a profile demands. This guide explains exactly what each error means, why it fires, and how to fix it, so the next red report becomes a thirty-second correction instead of an afternoon. You can reproduce every example in our FHIR Resource Validator, which runs entirely in your browser.

Cardinality — Reading the Numbers After Every Element

Open any resource page on hl7.org/fhir — say the Patient resource — and beside every element you will see a pair of numbers like 0..1, 1..1, or 0..*. This is cardinality, and it is defined in the FHIR specification's section on the Element Definition (the ElementDefinition.min and ElementDefinition.max properties). The first number is the minimum number of times the element must appear; the second is the maximum, where * means unbounded.

  • 0..1 — optional, at most once. Most elements. You may omit it; you may not repeat it.
  • 1..1 — required, exactly once. Observation.status and Observation.code are 1..1 in the base spec.
  • 0..* — optional, repeating. Patient.name and Observation.identifier are arrays.
  • 1..* — required and repeating. At least one must be present. Profiles frequently tighten an element to 1..*.

The error minimum cardinality not met means an element whose min is 1 (or higher) appeared zero times. The error maximum cardinality exceeded means you supplied more occurrences than max allows — typically an array where the spec permits a single value. Both are blocking errors: a conformant server will reject the resource.

Why a Field You Did Supply Still Reads as "Found 0"

The most confusing cardinality failures happen when you are certain the field is there. Three causes account for almost all of them. First, an empty value still counts as absent — "status": "" or "identifier": [] satisfies nothing, because FHIR's rules on empty elements (described in the specification's "Elements" page) say an element with no value is treated as not present. Second, you put the value at the wrong nesting level; code at the top of an Observation is not the same as component.code. Third — the subtle one — a profile bound to your resource raised the minimum. The base spec says Patient.identifier is 0..*, but US Core constrains it to 1..*, so a Patient with no identifier is perfectly valid against the base and invalid against US Core. The validator's error path tells you which element, and the profile URL in the message tells you which rule.

Profiles Are Where Cardinality Gets Stricter

A profile is a constrained version of a base resource, published as a StructureDefinition. The defining promise of profiling, per the FHIR specification's "Profiling" page, is that a profile may only narrow the base — it can raise a minimum from 0 to 1, lower a maximum from * to 1, or pin a fixed value, but it can never loosen what the base requires. This is why your resource can sail through a bare-resource check and fail the moment you validate against an implementation guide such as US Core or the International Patient Summary.

Concrete US Core examples are worth memorizing because you will hit them constantly. In the US Core Patient profile, name is raised to 1..* and identifier to 1..*; a Patient with neither fails with two minimum-cardinality errors. In US Core Observation, category becomes 1..* and code must carry a recognized code. These constraints exist because downstream systems — the ones consuming your data for treatment or reporting — depend on those fields always being present. The validator is enforcing a contract, not nitpicking.

Slicing — When One Array Element Must Mean a Specific Thing

Slicing is the harder concept, and the source of the cryptic does not match any known slice message. The problem it solves is this: an element like Patient.identifier is a repeating array, but a profile may need to say "one of these entries must be a Medical Record Number and another must be a Social Security Number." You cannot express that with cardinality alone, because cardinality only counts occurrences — it cannot say what each occurrence must be. Slicing, defined in the FHIR specification's "Profiling" page under "Slicing," partitions a repeating element into named slices, each with its own constraints and its own cardinality.

Every slice definition includes a discriminator — the rule the validator uses to decide which slice a given array entry belongs to. Discriminators have a type and a path. The common types, listed in the spec, are value (match on a fixed value, e.g. a coding system), pattern (match a structural pattern), type (match the data type), and profile (the entry must itself conform to a named profile). For US Core Patient identifiers, the discriminator is typically a pattern on identifier.system, so each entry is sorted into a slice by its system URL.

Decoding "Does Not Match Any Known Slice"

This message means the validator took one of your array entries, ran it past every slice's discriminator, and none matched. Picture a profile that slices Patient.identifier into an MRN slice (discriminated by system = http://hospital.example.org/mrn) and an SSN slice (system = http://hl7.org/fhir/sid/us-ssn). If you send an identifier with system set to http://hospital.example.org/MRN — uppercase, a typo, or simply a system the profile never defined — that entry matches no slice. Whether this is an error or a warning depends on the slicing's rules setting: open slicing tolerates extra unmatched entries, while closed slicing rejects them outright. The specification's slicing section documents open, closed, and openAtEnd precisely.

The second slicing failure is a slice-level cardinality error, and it reads almost like the resource-level one: Slice 'MRN' — minimum required = 1, but only found 0. This says the slice itself is mandatory and you supplied no entry matching its discriminator. The fix is not to add any identifier — it is to add one whose discriminating field matches the slice exactly. A common, maddening case is sending the right value but the wrong system: the data is "there," but because the discriminator is the system URL, the validator cannot assign it to the slice, so the slice counts as empty.

Understanding FHIR Validator Cardinality and Slicing Errors

A Fix-It Checklist for the Three Failure Modes

When a cardinality or slicing error appears, work through these in order. The validator's element path — something like Patient.identifier[0].system or Observation.component[1].code — tells you exactly where to look, the same way it does for the everyday structural checks covered in our FHIR Resource Validator.

  • Minimum cardinality not met (resource level) — confirm the element is present, non-empty, and at the right nesting level. If it looks present, check whether a profile raised the minimum; the message names the StructureDefinition. Add the required element with a real value.
  • Maximum cardinality exceeded — you sent an array where a single value belongs, or more repeats than the profile allows. Collapse the array to one value, or remove the surplus entries.
  • Does not match any known slice — inspect the discriminator (type and path) on the offending element. Make the entry's discriminating field exactly match a defined slice. Watch for case sensitivity, trailing slashes in system URLs, and version-specific code systems.
  • Slice minimum not met — a required slice has no matching entry. Add an entry whose discriminator value matches the slice, not merely another entry of the same element.

Where These Errors Bite During HL7 v2 Migration

Cardinality and slicing failures cluster heavily in migration work, when you bridge legacy HL7 v2 feeds into FHIR. A v2 PID segment carries patient identifiers in PID-3, often several repetitions with HL7 Table 0203 identifier-type codes. When you map those into a US Core Patient, each identifier has to land in the correct slice with the correct system URL — and v2 sources are notoriously loose about identifier types, so an MRN tagged as a generic identifier will sort into no slice. This is exactly the kind of defect to catch before the resource reaches a server. Our HL7 v2 to FHIR Mapper produces the resource, and validating the output immediately surfaces a mis-sliced identifier as a precise path rather than a vague server rejection. For background on how the two standards relate, our companion guide What Is FHIR? A Healthcare IT Guide walks through resources, R4, and the validation mindset.

Why Validating Locally Matters for PHI

Cardinality and slicing errors are, by their nature, things you debug iteratively — paste, read the path, fix, re-validate, repeat a dozen times. Every one of those iterations involves a real resource full of protected health information: identifiers, names, dates of birth, diagnoses. Routing that loop through a hosted validator means transmitting identifiable patient data to a third party on every pass, a clear concern under HIPAA's Security Rule and the GDPR. A browser-based validator keeps the entire debug loop on your machine — you can confirm in the network tab that nothing leaves — which is what makes it safe to paste production resources while you chase down a stubborn slice mismatch.

Knowing the Limits of a Lightweight Check

Be honest about scope. A fast browser validator is built for the constant question of "are my elements present and correctly sliced?" For full conformance against a published implementation guide — resolving every StructureDefinition, consulting terminology servers for value-set membership, and evaluating FHIRPath invariants — the official HL7 validator remains the reference. Use the quick local check to iterate at speed and to catch the cardinality and slicing mistakes that account for the overwhelming majority of real rejections, then run the heavyweight validator once for formal certification. The two are complementary: one keeps you moving, the other signs off.

Conclusion

Cardinality is counting — how many times an element may or must appear, expressed as min..max and tightened by profiles. Slicing is identity — which specific thing each entry in a repeating element must be, enforced by discriminators. Minimum cardinality not met means a required element or slice is missing or empty; does not match any known slice means an entry's discriminating field matched nothing the profile defined. Read the element path, check the profile, line up your discriminators, and these errors stop being mysterious. Keep the FHIR Resource Validator open as you work, pair it with the HL7 v2 to FHIR Mapper during migrations, and you will fix the next red report before it ever reaches a server — with patient data never leaving your browser.

← Back to Blog