Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/dhanyasukumaran1/fhir_query_validator/llms.txt

Use this file to discover all available pages before exploring further.

When you call validate_query() or validate_batch(), FHIR Query Validator does more than check syntax — it runs the query string through a multi-stage pipeline that verifies each structural component against the FHIR R4 specification. Understanding this pipeline helps you interpret validation results accurately, distinguish errors from warnings, and write queries that pass validation cleanly.

The validation pipeline

FHIR Query Validator processes each query string through four sequential stages. A failure at any stage produces an error, and the pipeline continues to later stages to surface as many problems as possible in a single pass.
1

Parse the query string

The validator splits the raw query string into its components: the resource type and the list of parameter-value pairs. Structural problems — such as malformed percent-encoding, missing resource types, or parameter names that contain illegal characters — are caught here before any FHIR-specific checks run.
parse_stage.py
from fhir_query_validator import FHIRQueryValidator

validator = FHIRQueryValidator()

# Malformed query string — no resource type
result = validator.validate_query("?family=Smith")
print(result.errors)
# ["Query string must begin with a resource type"]
2

Check the resource type

Once the query is parsed, the validator checks whether the resource type is a known FHIR R4 resource. Resource names are case-sensitive — patient is not valid; Patient is. If the resource type is unknown, the validator records an error and continues checking the remaining parameters anyway, so you see the full picture of what’s wrong.
resource_stage.py
result = validator.validate_query("Patients?family=Smith")
print(result.errors)
# ["Unknown FHIR resource type 'Patients'. Did you mean 'Patient'?"]
3

Check search parameters

For each parameter in the query string, the validator verifies that the parameter is defined for the given resource type in the FHIR R4 specification. This includes checking the parameter name itself and any modifier (the :exact or :missing suffix). Control parameters starting with _ are validated against the set of FHIR-defined control parameters.
param_stage.py
result = validator.validate_query("Patient?lastname=Smith")
print(result.errors)
# ["Unknown search parameter 'lastname' for resource type 'Patient'. Did you mean 'family'?"]
4

Check value formats

With the parameter name confirmed as valid, the validator checks that the value is formatted correctly for the parameter’s type. FHIR defines several value types — dates, tokens, references, quantities, URIs, and strings — each with its own format rules.
value_stage.py
result = validator.validate_query("Patient?birthdate=yesterday")
print(result.errors)
# ["Invalid date value 'yesterday' for parameter 'birthdate'. Expected ISO 8601 date format (e.g., 2024-01-15)"]

Errors vs. warnings

ValidationResult separates problems into two categories with different meanings.

Errors

The query violates the FHIR specification. A FHIR server is likely to reject it outright or return unexpected results. You should fix errors before using the query in production.

Warnings

The query is technically valid but may behave unexpectedly. Warnings highlight patterns that are legal but commonly misused, overly broad, or likely to return more (or fewer) results than intended.

What triggers errors

The resource type at the start of the query string is not a recognized FHIR R4 resource.
result = validator.validate_query("MedicalRecord?patient=Patient/123")
# Error: Unknown FHIR resource type 'MedicalRecord'
The parameter name is not defined for the specified resource type in the FHIR R4 specification.
result = validator.validate_query("Observation?result-value=5.5")
# Error: Unknown search parameter 'result-value' for resource type 'Observation'
The modifier applied to a parameter is not valid for that parameter’s type. For example, applying :exact to a date parameter is not supported.
result = validator.validate_query("Patient?birthdate:exact=1990-01-01")
# Error: Modifier ':exact' is not valid for parameter type 'date'
The value provided does not match the expected format for the parameter type. This includes invalid dates, unsupported token formats, and malformed reference values.
result = validator.validate_query("Encounter?date=2024/01/15")
# Error: Invalid date value '2024/01/15'. Expected ISO 8601 format (YYYY-MM-DD)
Some FHIR parameters accept only a specific set of string values defined by the specification. Providing an unlisted value is an error.
result = validator.validate_query("Encounter?status=completed")
# Error: Invalid value 'completed' for parameter 'status'.
#        Valid values: planned, arrived, triaged, in-progress, onleave, finished, cancelled

What triggers warnings

A query with only a resource type and no filter parameters is valid FHIR but returns all resources of that type. On large datasets this is typically unintentional.
result = validator.validate_query("Patient")
# Warning: Query has no search parameters. This will return all Patient resources.
#          Add search parameters to filter results.
The parameter is defined in FHIR R4 but has been marked as deprecated in favor of a newer alternative.
result = validator.validate_query("Patient?address=123 Main St")
# Warning: Parameter 'address' is deprecated. Consider using 'address-city',
#          'address-state', or 'address-postalcode' for more precise filtering.
A date range spanning many decades is valid but may indicate an inadvertent omission of a boundary that would significantly restrict results.
result = validator.validate_query("Observation?date=ge1900-01-01")
# Warning: Date range starting in 1900 will match a very large number of resources.
#          Consider narrowing the date range.
A chained parameter with many hops is valid FHIR but may not be supported by all servers and can be expensive to execute.
result = validator.validate_query("DiagnosticReport?result.subject.organization.name=Acme")
# Warning: Chained parameter depth of 3 may not be supported by all FHIR servers.

The ValidationResult object

Every call to validate_query() returns a ValidationResult object. Every item in the list returned by validate_batch() is also a ValidationResult. The object has three attributes.
result_structure.py
from fhir_query_validator import FHIRQueryValidator

validator = FHIRQueryValidator()
result = validator.validate_query("Patient?family=Smith")

# Boolean — True if the query has no errors (warnings are allowed)
print(result.is_valid)     # True

# List of strings — each string describes one error
print(result.errors)       # []

# List of strings — each string describes one warning
print(result.warnings)     # []
is_valid is True when there are no errors. A query with warnings but no errors is considered valid — is_valid will be True. Warnings indicate potential issues but do not make a query invalid.

Working with results

single_query.py
from fhir_query_validator import FHIRQueryValidator

validator = FHIRQueryValidator()

result = validator.validate_query("Observation?code=8867-4&patient=Patient/123")

if result.is_valid:
    if result.warnings:
        print("Query is valid with warnings:")
        for warning in result.warnings:
            print(f"  [WARN] {warning}")
    else:
        print("Query is valid")
else:
    print("Query is invalid:")
    for error in result.errors:
        print(f"  [ERROR] {error}")
    for warning in result.warnings:
        print(f"  [WARN]  {warning}")

Common validation scenarios

The following examples show query patterns you are likely to encounter and the validation feedback each produces.
Token parameters accept values in the format system|code. The pipe character separates the code system URI from the code value. Both parts are optional — you can search by code alone or system alone.
validator = FHIRQueryValidator()

# Search by LOINC code only
result = validator.validate_query("Observation?code=8867-4")
print(result.is_valid)  # True

# Search with full system|code token
result = validator.validate_query("Observation?code=http://loinc.org|8867-4")
print(result.is_valid)  # True

# Malformed token — double pipe
result = validator.validate_query("Observation?code=http://loinc.org||8867-4")
print(result.is_valid)  # False
print(result.errors)    # ["Malformed token value 'http://loinc.org||8867-4'"]
You can specify a date range by repeating the same parameter with different prefixes. Both instances must be valid.
result = validator.validate_query(
    "Observation?date=ge2024-01-01&date=le2024-12-31"
)
print(result.is_valid)  # True

# One end of the range has an invalid date format
result = validator.validate_query(
    "Observation?date=ge2024-01-01&date=le2024-13-01"
)
print(result.is_valid)  # False
print(result.errors)    # ["Invalid date value '2024-13-01': month 13 is out of range"]
Reference parameters point to other FHIR resources. They accept a relative reference (Patient/123), an absolute URL, or a plain ID.
# Relative reference (preferred)
result = validator.validate_query("Observation?patient=Patient/123")
print(result.is_valid)  # True

# Absolute reference
result = validator.validate_query(
    "Observation?patient=https://fhir.example.com/r4/Patient/123"
)
print(result.is_valid)  # True

# Plain ID (valid but may not work on all servers)
result = validator.validate_query("Observation?patient=123")
print(result.is_valid)   # True
print(result.warnings)   # ["Plain ID reference '123' for 'patient' may require a resource type prefix on some servers"]

Next steps

Basic validation guide

Step-by-step instructions for integrating validation into your Python application.

Validation rules reference

The complete list of error codes and warning codes produced by the validator.

Build docs developers (and LLMs) love