Linting & validation
octofhir-sof has two offline checkers for ViewDefinitions:
validate— structural spec invariants only, no FHIR package or database. Covers FH06–FH10.lint— schema-driven selector and generated-SQL checks against a FHIR package (--package), and/or the portable FHIRPath subset (--shareable). Covers FH01–FH05 (schema), FH06–FH10 (structure, also run byvalidate), and FH11 (shareable).
Both emit rustc-style diagnostics by default, or --json / --sarif (SARIF
2.1.0) for CI code scanning. Each FH* finding links to its
rule reference page.
The rules
Section titled “The rules”| Code | Severity | What it flags |
|---|---|---|
| FH01 | error | Unknown FHIR element (with a did-you-mean suggestion) |
| FH02 | warning | Choice element not narrowed with ofType() |
| FH03 | warning | Complex element selected into a scalar column |
| FH04 | warning | Array-valued element into a scalar column |
| FH05 | warning | Reference into a scalar without getReferenceKey() |
| FH06 | error | Invalid SQL name (column / constant / view name) |
| FH07 | error | More than one of forEach / forEachOrNull / repeat |
| FH08 | error | Duplicate output column name |
| FH09 | error | unionAll branches with mismatched shape |
| FH10 | error | Missing resource, or a view that produces no columns |
| FH11 | error/warn | FHIRPath outside the ShareableViewDefinition subset |
FH01–FH05 need a schema (--package); FH06–FH10 are structural; FH11 is opt-in
with --shareable.
Schema-driven linting
Section titled “Schema-driven linting”octofhir-sof lint view.json --package hl7.fhir.r4.coreoctofhir-sof lint view.json --package hl7.fhir.r5.core --version 5.0.0--package enables the selector checks (FH01–FH05) by walking each FHIRPath
selector against the real shape of the resource. With --version, the package
is installed through the canonical manager if missing; without it, only an
already-present package is used (offline). See
FHIR versions.
Shareable subset (--shareable)
Section titled “Shareable subset (--shareable)”The Shareable View Definition profile requires runners to implement only a minimal FHIRPath subset, so a view that stays inside it runs unchanged on any conformant engine. FH11 walks every FHIRPath expression in the view and flags anything outside that subset:
octofhir-sof lint view.json --shareableThis check needs no package — it is purely a FHIRPath analysis. The required
subset allows the functions where, exists, empty, extension, ofType,
first (plus the SQL-on-FHIR getResourceKey/getReferenceKey), the boolean
operators and/or/not, math + - * /, the comparisons = != > <=, the
indexer [], and String / Integer / Decimal / Boolean literals. The
experimental join, lowBoundary, highBoundary warn; everything else is an
error.
Exempt an engine-registered custom FHIRPath function so the strict pass does not hard-fail it (repeatable):
octofhir-sof lint view.json --shareable --allow-fn myCustomFnYou can combine --package and --shareable in one run.