OperationOutcome carries two closely related fields that both do the same job: location and expression. Both are pointers into the resource under evaluation, saying "here is the offending element." One is older and being deprecated; the other is the current preferred form. Knowing which is which — and knowing how to parse each — is what makes an OperationOutcome consumer useful. The site's OperationOutcome reader resolves both against a paste-in resource. For the wider FHIR framing, our FHIR coverage for clinical teams has more.
The Two Fields
location— a legacy array of dot-path strings pointing at the elementexpression— an array of FHIRPath expressions pointing at the element
Both live on the same issue entry. Both are arrays because one issue can point at multiple locations — a duplicate detected across two entries in a Bundle, for instance. Consumers should read both; older servers only produce location, newer ones prefer expression.
What `location` Looks Like
A location string uses XPath-flavored syntax with array indexes:
`` "location": ["Patient.name[0].family"] ``
or
`` "location": ["/f:Patient/f:name[1]/f:family"] ``
Two flavors are in the wild — dot-path and XPath. Callers have to handle both, and the mixing is one of the reasons location is deprecated.
What `expression` Looks Like
expression uses FHIRPath, the same language the invariants use:
`` "expression": ["Patient.name[0].family"] ``
Cleaner, one flavor, and it can be evaluated against the resource to jump directly to the offending element. The OperationOutcome reader evaluates expression when you paste both an outcome and a sample resource.
Which To Emit
- Emit
expressionon new servers - Continue to emit
locationfor compatibility if consumers depend on it - Prefer FHIRPath dot-path form when emitting
location, since it is closer toexpressionand easier to migrate
For custom validators, the emit-both pattern is safest. For the design side, designing your own OperationOutcome for a custom validator covers the shape.
Which To Consume
Consume expression first if present, location as fallback. A well-written OperationOutcome consumer normalizes both into an internal representation and lets the rest of the code depend on it.
Callers that only consume location miss issues from newer servers that emit expression only. Callers that only consume expression miss issues from older servers.
Multiple Pointers Per Issue
An issue can point at multiple elements. A referential-integrity error might point at both the referrer and the target. A cross-field validation might point at both fields involved. Both location and expression are arrays for this reason.
Callers that read only the first element lose context. Handle the array, not just the first entry.
Resolving Pointers Against The Resource
An expression pointer resolves against the resource that was being evaluated. The consumer needs both the outcome and the resource to render "here is what's wrong" usefully. Without the resource, the pointer is a string in space.
The reader takes both as input for exactly this reason: paste the outcome, paste the resource, get an annotated view.
What Happens On A Bundle
For OperationOutcome from a batch or transaction Bundle, the expression pointers usually refer to entries within the Bundle: Bundle.entry[3].resource.name[0].family. That is deep, and callers that flatten to just the resource lose the entry context. Preserve the full path.
For the code-vocabulary side of the same triage, issue.code vocabulary and what it actually means covers the reasons.
The Short Version
expression is the current form; location is legacy. Consumers handle both. Pointers are arrays, not single values. Resolve against the original resource to render usefully. For the base pattern, reading an OperationOutcome for the first time is the entry.

Sources
- HL7 canonical OperationOutcome specification covering - HL7 canonical OperationOutcome specification covering location and expression fields