Validation Support Repository Options

 

This page describes various setting that can be applied to the validation support repository in order to control validation.

Note that these settings apply to the FHIR Storage (RDBMS) module that is being used for Validation Support.

Validating References

 

The Local Reference Policy setting can be used to control the behavior when validating a reference from one resource to another. This setting should be carefully considered, since validating a reference usually means loading the target resource and potentially parsing it and extracting parts of it. In performance sensitive environments, this can have a measurable effect on throughput, although it does improve the quality of the validation.

This setting should be configured on the FHIR Storage repository whose resources are being validated (as opposed to the FHIR Storage repository being used for validation support, if these are not the same repository).

The following values may be used:

  • NOT_VALIDATED – Don't validate references.
  • VALIDATE_EXISTS – Validate that the reference is valid and the target exists, but do not validate that the target resource is fully appropriate as a target for the reference.
  • VALIDATE_TARGET – Validate that the reference is valid, but also that the target resource is appropriate for the given reference (it conforms to the right profiles, is of the right type, etc.)

Unknown CodeSystems

 

A ValueSet can list codes from an unknown CodeSystem: one the server does not have, in any version or at the version the ValueSet names (ValueSet.compose.include.version). The server then cannot tell whether a code is in the ValueSet. What happens, and what you can do about it, depends on the operation.

Validating Resources

The Unknown CodeSystem Validation Policy determines what the validator should do if it encounters a Coding in a resource where the CodeSystem (Coding.system) is unknown.

  • GENERATE_ERROR – (default) Add an error to the validation results (will cause validation to fail)
  • GENERATE_WARNING – Add a warning to the validation results (will not cause validation to fail). A code that a ValueSet lists from such a CodeSystem then passes a required binding to that ValueSet with the warning. A code the ValueSet does not list still fails the binding, because the ValueSet cannot contain it, unless the ValueSet also includes the whole CodeSystem, a filter on it, or another ValueSet that uses it.

This setting applies only to resource validation ($validate, and validation on create and update). It does not change the operations in the next section.

Expansion, Code Validation, Searches and Permissions

For a ValueSet that uses an unknown CodeSystem:

  • ValueSet/$expand returns an error naming the unknown CodeSystem, as url, or the unknown version, as url|version.
  • ValueSet/$validate-code rejects the code and names the unknown CodeSystem.
  • Searches that use the ValueSet with :in or :not-in fail with HTTP 400.
  • Pre-expansion of the ValueSet fails, with the status FAILED_TO_EXPAND.
  • The Block Unless Code in ValueSet permissions deny access.
  • Where :in or :not-in is matched in memory rather than by a database search, the match cannot be decided:
    • Permissions and SMART scopes with a search filter, such as FHIR_READ_ALL_OF_TYPE with Observation?code:not-in=..., deny the read.
    • Subscriptions use a database search instead, which fails naming the CodeSystem.
    • Bulk Export _typePostFetchFilterUrl filters leave the resource out.

To have the codes checked, give the server a CodeSystem to check them against:

Uploading the CodeSystem does not update ValueSets that are already pre-expanded, including those that failed: re-expand them with $invalidate-expansion.

An Unknown Version of a CodeSystem the Server Has

When a ValueSet names an unknown version of a CodeSystem, one the server does not have while it has another version of that CodeSystem, the Use Current Version for Unknown CodeSystem Version setting determines what happens.

  • Disabled (default): the codes are treated as unknown, as described in the previous section.
  • Enabled: the codes are checked against the current version of the CodeSystem instead, with a warning naming both versions. A code in the current version is accepted, and a code not in it is rejected. This applies to resource validation and to all the operations in the previous section.

When the setting is enabled:

  • A ValueSet that includes the whole CodeSystem, or uses a filter, takes its codes from the current version, which may have codes the named version does not.
  • The Block Unless Code in ValueSet permissions check a code against the current version only if that version has it. For a code the current version lacks, both BLOCK_FHIR_READ_UNLESS_CODE_IN_VS and BLOCK_FHIR_READ_UNLESS_CODE_NOT_IN_VS deny the read, as with the setting disabled, because the code might still be in the version the ValueSet names.

Whether enabled or not:

  • Codes from a CodeSystem that is unknown in every version are rejected.
  • A ValueSet that only a Remote Terminology Service has is checked by that service, not by this setting.
  • Changing the setting does not update ValueSets that are already pre-expanded. They keep their earlier result, including FAILED_TO_EXPAND, until they are pre-expanded again.
  • When a FHIR Storage module uses another module for validation support, set this setting to the same value on both modules. Some of the operations above read it from the module that stores the ValueSet, and others from the module that provides validation support.

Handling Multiple Codings

 

The default behaviour for validation of CodeableConcept elements is to validate each Coding within the element, and consider the CodeableConcept to be valid if at least one coding is valid. This means that a CodeableConcept with one valid coding and one non-valid coding will be considered valid in the default behavior. This is generally desirable, but may cause problems in certain scenarios.

In some scenarios, it may be more desirable to consider the CodeableConcept as valid only if all Codings pass validation.

One example is a Patient message containing two communications languages, one incorrect (en_US) and the other correct (en), which is POSTed to {Smile CDR URL}/Patient/$validate:

{
    "resourceType": "Patient",
    "name": [
        {
            "family": "Doe",
            "given": [
                "John"
            ]
        }
    ],
    "birthDate": "1912-04-14",
    "communication": [
        {
            "language": {
                "coding": [
                    {
                        "system": "urn:ietf:bcp:47",
                        "code": "en_US",
                        "display": "US English"
                    },
                    {
                        "system": "urn:ietf:bcp:47",
                        "code": "en",
                        "display": "English"
                    }
                ]
            }
        }
    ]
}

The response would contain the following issue:

{
   "severity": "error",
   "code": "processing",
   "diagnostics": "Unknown code 'urn:ietf:bcp:47#en_US' for in-memory expansion of ValueSet 'http://hl7.org/fhir/ValueSet/languages'",
   "location": [
       "Patient.communication[0].language",
       "Line 15, Col 14"
   ]
}

This contrasts with what happens with a request containing a single incorrect language: en_US:

{
    "resourceType": "Patient",
    "name": [
        {
           "family": "Doe",
           "given": [
              "John"
           ]
        }
    ],
    "birthDate": "1912-04-14",
    "communication": [
        {
            "language": {
                "coding": [
                    {
                        "system": "urn:ietf:bcp:47",
                        "code": "en_US",
                        "display": "US English"
                    }
                ]
            }
        }
    ]
}

In this case, the smilecdr response would contain the following, which contrasts sharply with the first scenario:

        {
            "severity": "information",
            "code": "processing",
            "details": {
                "coding": [
                    {
                        "system": "http://hl7.org/fhir/java-core-messageId",
                        "code": "Terminology_TX_NoValid_3_CC"
                    }
                ]
            },
            "diagnostics": "None of the codings provided are in the value set 'Common Languages' (http://hl7.org/fhir/ValueSet/languages|4.0.1), and a coding is recommended to come from this value set) (codes = urn:ietf:bcp:47#en_US)",
            "location": [
                "Patient.communication[0].language",
                "Line 15, Col 14"
            ]
        }

If you want to require all Codings within the CodeableConcept to be valid in order to consider the CodeableConcept valid, you may set the Accept All Codings Only setting to true (the default is false).

After setting this configuration to true, the response to the first two communication language request above will contain:

{
   "severity": "information",
   "code": "processing",
   "diagnostics": "None of the codings provided are in the value set 'Common Languages' (http://hl7.org/fhir/ValueSet/languages|4.0.1), and a coding is recommended to come from this value set) (codes = urn:ietf:bcp:47#en_US, urn:ietf:bcp:47#en)",
   "location": [
      "Patient.communication[0].language",
      "Line 15, Col 14"
   ]
}

Allowing Database Validation Override

 

In some cases, you may want your database-stored CodeSystem and ValueSet resources to take precedence over the built-in HL7 definitions. This is useful when you need to override a built-in terminology resource with a custom or different version of that resource.

By default, when the validator needs to look up a terminology resource (such as a CodeSystem or ValueSet), it checks the built-in HL7 definitions first. If the resource is found there, it is used for validation. This means that even if you have stored a custom version of a standard HL7 CodeSystem in your database, the built-in version will be used instead.

To change this behavior, enable the Allow Database Validation Override setting. When this setting is enabled (true), the JPA validation support (database-stored resources) is placed before the default profile validation support in the chain. When disabled (false, the default), the built-in definitions take precedence.

This setting is particularly useful when:

  • You need to use a custom version of a standard terminology resource
  • You want to override built-in CodeSystem definitions with updated versions
  • Your organization has specific terminology requirements that differ from the standard HL7 definitions
Enabling this setting means that database-stored resources will override built-in HL7 definitions. Ensure that your database-stored resources are correct and complete before enabling this setting, as incorrect terminology resources could cause validation failures.

Code Display Mismatch Policy

 

When storing and communicating coded fields, it is generally a good idea to transmit the concept display name as well as the actual code. This is helpful for consumers of your data because it allows them to display meaningful text to users even if they do not have the given CodeSystem locally available in their own system.

In this context, coded fields refers to the datatypes CodeableConcept and Coding. The code datatype is also used to convey coded elements, but it does not allow for a display name, so it is not relevant here.

When validating these coded fields, it is a good idea to ensure that the display name is actually correct for the given code. The Code Display Mismatch Policy determines how strict the validator should be in validating these display names.

If the coded element being validated does not have a display name present, this is treated by the validator as if the display name is correct (i.e. no error is generated), unless the profile being validated explicitly requires a display name to be present.

The options for the Code Display Mismatch Policy setting are:

  • ERROR – If the display name is not correct, an error is generated. The concept is considered to be invalid, and additional errors may also be raised if the profile requires a valid concept from a specific ValueSet.
  • WARNING – If the display name is not correct, a warning is generated. If the concept is otherwise valid for the ValueSet being validated against, no further errors are generated.
  • INFORMATION – No validation messages are emitted even if the display name is not correct.

Validation Support Cache

 

The Validation Support Repository uses a cache to store in-memory the results of various queries for data that the validator needs. This includes:

  • Fetching required resources such as StructureDefinition and ValueSet resources from the FHIR repository and NPM/Package storage.
  • Validating concepts
  • Resource lookups, concept validations, concept mappings, etc. performed by any configured Remote Terminology Service

The cache can be configured using the Validation Support Cache Expiry and Validation Support Cache Size settings.

Note that this cache does not apply to StructureDefinition resource lookups. This resource type is kept in a non-expiring cache, since the FHIR Instance Validator requires this. In order to flush the StructureDefinition cache (e.g. because a StructureDefinition has been modified in-place) requires restarting the FHIR Storage module, or restarting the running Smile CDR process(es).

Having a cache with appropriate capacity is critical to efficient performance of the validator. If you require no terminology functions or infrequently need these functions, consider reducing these values (a short timeout such as 5 minutes might be appropriate). Similarly, if you are running a development server where you expect underlying resources to change frequently, you may want to consider reducing these values. Setting either of these values to 0 will disable the cache completely, which will severely degrade validation performance but could be useful if you are performing profile development.

On the other hand, if you are running a server with heavy validation requirements, such as large number of profiles, a large number of distinct concepts being validated, etc. you may want to consider increasing these settings. It is important to monitor server memory usage after increasing these values to ensure that you are not overloading the amount of memory available.

The current capacity of the cache can be monitored with OpenTelemetry using the instrumentation io.hapifhir.validation_support_chain.