LinuxForHealth / FHIR

The LinuxForHealth FHIR® Server and related projects
https://linuxforhealth.github.io/FHIR
Apache License 2.0
333 stars 156 forks source link

If display value is invalid exception message states it is an incorrect code #3665

Closed henryhbk closed 2 years ago

henryhbk commented 2 years ago

If the display value for a CodeableConcept does not match the codeset, the error thrown is misleading:

{
            "severity": "information",
            "code": "code-invalid",
            "details": {
                "text": "appointment-5: A code in this element should be from the specified value set 'http://hl7.org/fhir/ValueSet/c80-practice-codes' if possible"
            },
            "expression": [
                "Appointment.specialty[0]"
            ]
        },

In that case I had: "419192003", "http://hl7.org/fhir/ValueSet/c80-practice-codes", "General Internal Medicine"

2022-05-26_12-02-56

where the correct display value was just "Internal Medicine". A better error message would state that the validation was failing on the display rather than the code itself not being from the codeset.

duplicatable with the values above (or any change to the display of a CodeableConcept)

issue discussed with @lmsurpre

lmsurpre commented 2 years ago

I missed it when we talked before, but the system is whats wrong in your example. The "http://hl7.org/fhir/ValueSet/c80-practice-codes" valueset consists of codes from SNOMED CT.

Therefor, the error is right to say that the code you used doesn't exist in http://hl7.org/fhir/ValueSet/c80-practice-codes ...just for a different reason than I assumed.

With that said, I'm pretty sure I hit this same situation from an invalid code display value before and so I confirmed the following: after fixing the system to "http://snomed.info/sct", I still get the appointment-5 constraint failure. After some digging, I found that this is due to the fact we don't have SNOMED CT configured on the server by default (that would require configuring either our GraphTermServiceProvider or our RemoteTermServiceProvider). However, in such cases I think it would be better to call this constraint met and instead log an informational message to indicate that we didn't actually check the display value.

In this particular case, its just a "preferred" binding and so the only difference is the contents of the informational message that comes back. However, this change has bigger implications for "required" bindings to valuesets that compose CodeSystems that aren't configured on the server.

punktilious commented 2 years ago

Acceptance criteria?

lmsurpre commented 2 years ago

QA:

  1. Add a ValueSet to the registry which enumerates concept from a made up CodeSystem
    • this can be provided via either a test RegistryResourceProvider or by setting serverRegistryResourceProviderEnabled to true and posting the ValueSet to the server
  2. Define a profile that has a binding to this valueset with strength=required
    • this can be done with our ProfileBuilder class under fhir-profile/src/test
  3. Create an instance that claims conformance to this profile and include a Coding.display value
  4. Validate the instance

Because the CodeSystem is not defined, we expect to see an informational warning that says we couldn't validate the display value of the code. However, we should not fail the validation just because we couldn't validate the display string.

punktilious commented 2 years ago

Profile http://hl7.org/fhir/us/core/StructureDefinition/us-core-diagnosticreport-note has a required binding to ValueSet-us-core-diagnosticreport-category.json which includes the following:

...
 "compose": {
        "include": [
            {
                "system": "http://loinc.org",
                "concept": [
                    {
                        "code": "LP29684-5",
                        "display": "Radiology"
                    },
                    {
                        "code": "LP29708-2",
                        "display": "Cardiology"
                    },
                    {
                        "code": "LP7839-6",
                        "display": "Pathology"
                    }
                ]
            }
        ]
    },

Creating a DiagnosticReport resource referencing this profile:

{
    "resourceType": "DiagnosticReport",
    "id": "qa-3665",
    "meta": {
        "versionId": "P0XILZwPTL",
        "lastUpdated": "2022-05-13T14:23:02.346894-04:00",
        "source": "TqeXb6FADf",
        "profile": [
            "http://hl7.org/fhir/us/core/StructureDefinition/us-core-diagnosticreport-note|5.0.1"
        ]
    },
    "status": "preliminary",
    "category": [
        {
            "coding": [
                {
                    "system": "http://loinc.org",
                    "code": "LP29684-5",
                    "display": "Radiolog"
                }
            ],
            "text": "K6VCF06qAs"
        }
    ],
    "code": {
        "coding": [
            {
                "system": "FRQduADn2m",
                "version": "VP8lAWtGEL",
                "code": "2l38coFrep",
                "display": "owdwa0uRSc",
                "userSelected": true
            }
        ],
        "text": "ofnY5uJdnh"
    }
}

and specifying the header Prefer: return=OperationOutcome, we see:

...
    {
      "severity": "information",
      "code": "not-supported",
      "details": {
        "text": "Unable to validate display value 'Radiolog' for code 'LP29684-5' in system 'http://loinc.org'"
      },
      "expression": [
        "DiagnosticReport.category[0]"
      ]
    },

which is the expected response, because the display value Radiolog can't be verified against the underlying LOINC code-system.

https://www.hl7.org/fhir/valueset.html#designations

Any display name for a concept provided in the value set is for display to a human user. The display in the Coding that results from a user selecting a concept from the expansion must be taken from the underlying code system definition, even if a value set is referenced explicitly in the Coding (e.g. by an extension). The correct display for a code can be determined by a $lookup operation. Any alternative display specified in the value set would go in CodeableConcept.text, perhaps appended to the UI label for the matching data element.