Linter Rules to Catch the Ten Most Common Search Mistakes

Editorial illustration in vaporwave-pastel style depicting a ten-row linter output checklist with magenta warning markers per common FHIR search mistake

A FHIR search linter is a small pile of rules that check a query string before it hits the server. The site's FHIR search query auditor implements the rules below. They are the payoff-heavy list — each catches a class of mistake that produces wrong-but-quiet results in production. For the wider FHIR framing, additional MPI and patient-matching notes has more.

The Ten Rules

### 1. Unknown parameter name

The parameter is not declared in the CapabilityStatement for the resource type. Server silently ignores it, returns unfiltered results. Warning: rename to a canonical parameter or drop.

### 2. Unencoded reserved character in value

Comma, ampersand, pipe, colon in a raw value truncates the search. Warning: percent-encode. For the deep dive, reserved characters in search values that break silently walks through the encoding rules.

### 3. Date without timezone

?date=2026-07-11 interpreted in server-local time. Warning: append explicit UTC or offset.

### 4. Sort without unique tiebreaker

_sort=date alone. Warning: append _id for stable pagination. For the mechanic, sort order that survives resource updates is the entry.

### 5. :not without :missing companion

?code:not=X misses resources where code is absent. Warning: consider adding code:missing=true if absence should be included.

### 6. _offset in a paginated multi-page query

Signals fragile pagination when the underlying set changes. Warning: prefer the next link. For the pagination side, using _count and _offset without losing consistency covers it.

### 7. Duplicate parameter with different modifiers

?code=X&code:not=Y — reduces to the more restrictive one, not both. Warning: use OR/AND explicitly.

### 8. Chained parameter without target parameter declared

?subject.name=Smith requires the target resource to support name search. Warning: check the target's CapabilityStatement.

### 9. Composite parameter with wrong halves order

?component-code-value-quantity=…$… — spec fixes the order. Warning: verify the composite definition.

### 10. Requested _count above server cap

_count=10000 on a server that caps at 100. Warning: expect fewer results per page, plan pagination.

What The Ten Catch

Every rule maps to a real class of wrong-but-quiet result. Rules 1, 2, 3, 5, 7 catch queries that return the wrong set. Rules 4, 6, 10 catch pagination shapes that produce inconsistent results across pages. Rules 8, 9 catch queries that many servers accept but interpret differently.

None of the ten is a spec violation. Every one is a shape that fails to surface an error but produces incorrect results.

Beyond the Ten

Additional rules that show up in the auditor but did not make the top ten:

  • _include and _revinclude with unsupported target types
  • _summary values that not every server implements
  • _since semantics that vary by server
  • Prefix sa and eb on date ranges — semantics are subtle
  • _language search that not every server implements

Each is worth its own audit case when you hit it. The top ten cover the daily surface.

Codifying These Rules Locally

The right pattern is to codify these rules in the team's own linter, not just rely on a public tool. That way the rules can be run in CI on the query strings the codebase generates. For the team side, codifying your team's FHIR search conventions covers the pattern.

The Short Version

Ten rules cover the everyday quiet-wrong queries. Encode reserved chars, timezone dates, tiebreak sorts, prefer next over _offset, watch :not vs :missing. For the wider quiet-wrong category, the FHIR searches that look correct but are wrong is the entry.

Vaporwave-pastel diagram of a ten-row linter output checklist, each row flagging one of the common mistake classes with a magenta warning marker, on a soft dusk-purple background

Sources