A public tx.fhir.org validation response emits two inactive-code issues for the submitted code. The first issue correctly points at expression: ["code"]; the follow-up inactive warning is about the same submitted code but has no expression, so clients cannot attach that warning back to the offending input element.
Public repro
curl -sS \
-H 'Accept: application/fhir+json' \
-H 'Content-Type: application/fhir+json' \
--data-binary @- \
'https://tx.fhir.org/r4/CodeSystem/$validate-code' <<'JSON'
{
"resourceType": "Parameters",
"parameter": [
{"name": "url", "valueUri": "http://snomed.info/sct"},
{"name": "code", "valueCode": "155728006"},
{"name": "activeOnly", "valueBoolean": true}
]
}
JSON
Expected
Both inactive-related issues are about the submitted code parameter, so both should carry expression: ["code"].
Expected issue shape:
{
"issue": [
{
"severity": "error",
"code": "business-rule",
"details": {"text": "The concept '155728006' is valid but is not active"},
"expression": ["code"]
},
{
"severity": "warning",
"code": "business-rule",
"details": {"text": "The concept '155728006' has a status of inactive and its use should be reviewed"},
"expression": ["code"]
}
]
}
Observed
The warning has no expression:
{
"resourceType": "Parameters",
"parameter": [
{"name": "result", "valueBoolean": false},
{"name": "inactive", "valueBoolean": true},
{
"name": "message",
"valueString": "The concept '155728006' has a status of inactive and its use should be reviewed; The concept '155728006' is valid but is not active"
},
{
"name": "issues",
"resource": {
"resourceType": "OperationOutcome",
"issue": [
{
"severity": "error",
"code": "business-rule",
"details": {"text": "The concept '155728006' is valid but is not active"},
"expression": ["code"]
},
{
"severity": "warning",
"code": "business-rule",
"details": {"text": "The concept '155728006' has a status of inactive and its use should be reviewed"}
}
]
}
}
]
}
Why this happens
The inactive state stores a path, and the final inactive warning uses that stored path directly:
// tx/workers/validate.js
if (inactive.value) {
result.addParamBool('inactive', inactive.value);
...
let m = this.worker.i18n.translate('INACTIVE_CONCEPT_FOUND', this.params.HTTPLanguages, [vstatus.value, tcode]);
msg(m);
op.addIssue(new Issue('warning', 'business-rule', inactive.path, 'INACTIVE_CONCEPT_FOUND', m, 'code-comment'));
// Problem: this depends on inactive.path already being the code element path.
}
But the active-only path stores the parent path, while the immediate error correctly uses addToPath(path, 'code'):
// tx/workers/validate.js
} else if (this.params.activeOnly && await cs.isInactive(loc.context)) {
result = false;
if (role !== 'not in') {
inactive.value = true;
inactive.path = path;
// Problem: for a direct code validation, path can be empty, so the later warning has no expression.
// It should preserve the same path used by the immediate issue below.
vstatus.value = await cs.getStatus(loc.context);
let msg = this.worker.i18n.translate('STATUS_CODE_WARNING_CODE', this.params.HTTPLanguages, ['not active', code]);
messages.push(msg);
op.addIssue(new Issue('error', 'business-rule', addToPath(path, 'code'), 'STATUS_CODE_WARNING_CODE', msg, 'code-rule'));
// This issue correctly points at expression ["code"].
}
}
A public
tx.fhir.orgvalidation response emits two inactive-code issues for the submitted code. The first issue correctly points atexpression: ["code"]; the follow-up inactive warning is about the same submitted code but has noexpression, so clients cannot attach that warning back to the offending input element.Public repro
Expected
Both inactive-related issues are about the submitted
codeparameter, so both should carryexpression: ["code"].Expected issue shape:
{ "issue": [ { "severity": "error", "code": "business-rule", "details": {"text": "The concept '155728006' is valid but is not active"}, "expression": ["code"] }, { "severity": "warning", "code": "business-rule", "details": {"text": "The concept '155728006' has a status of inactive and its use should be reviewed"}, "expression": ["code"] } ] }Observed
The warning has no
expression:{ "resourceType": "Parameters", "parameter": [ {"name": "result", "valueBoolean": false}, {"name": "inactive", "valueBoolean": true}, { "name": "message", "valueString": "The concept '155728006' has a status of inactive and its use should be reviewed; The concept '155728006' is valid but is not active" }, { "name": "issues", "resource": { "resourceType": "OperationOutcome", "issue": [ { "severity": "error", "code": "business-rule", "details": {"text": "The concept '155728006' is valid but is not active"}, "expression": ["code"] }, { "severity": "warning", "code": "business-rule", "details": {"text": "The concept '155728006' has a status of inactive and its use should be reviewed"} } ] } } ] }Why this happens
The inactive state stores a path, and the final inactive warning uses that stored path directly:
But the active-only path stores the parent path, while the immediate error correctly uses
addToPath(path, 'code'):