Skip to content

SNOMED: a ValueSet filter naming an unknown concept is a 400, not a 500 - #357

Open
jmandel wants to merge 1 commit into
HealthIntersections:mainfrom
jmandel:fix/snomed-unknown-filter-concept
Open

jmandel wants to merge 1 commit into
HealthIntersections:mainfrom
jmandel:fix/snomed-unknown-filter-concept

Conversation

@jmandel

@jmandel jmandel commented Nov 8, 2026

Copy link
Copy Markdown
Contributor

A $expand whose SNOMED CT filter names a concept that the edition does not have now answers 400 (error / invalid / tx-issue-type vs-invalid). Before this change it answered 500 (exception / invalid-data). Examples are concept in 41000147108 (a refset that only exists in another edition) and concept is-a 584021000052104. The value set is invalid, so this is a client error, not a server failure.

curl -s -H 'Content-Type: application/fhir+json' 'http://localhost:3000/r4/ValueSet/$expand' -d '{"resourceType":"Parameters","parameter":[{"name":"valueSet","resource":{"resourceType":"ValueSet","status":"active","compose":{"include":[{"system":"http://snomed.info/sct","filter":[{"property":"concept","op":"in","value":"41000147108"}]}]}}}]}'
  • Before: HTTP 500, {"severity":"error","code":"exception","details":{"text":"The SNOMED CT Concept 41000147108 is not known","coding":[{"system":".../tx-issue-type","code":"invalid-data"}]},"diagnostics":"..."}
  • After: HTTP 400, {"severity":"error","code":"invalid","details":{"text":"The SNOMED CT Concept 41000147108 is not known","coding":[{"system":".../tx-issue-type","code":"vs-invalid"}]}}

This matches what an unknown concept in ECL already gets: the same Issue, error / invalid / vs-invalid, handleAsOO(400) (tx-ecosystem snomed-expand-ecl-unknown-concept). The text stays "The SNOMED CT Concept X is not known". That is the text ECL wraps in INVALID_ECL, and there is no ECL expression to quote here, so the issue carries no message id.

Change. In tx/cs/cs-snomed.js, the concept filter helpers throw this issue instead of a plain Error. That covers =, is-a, descendent-of, child-of, generalizes, descendent-leaf, is-not-a and in, for both the concept and code properties. ECL evaluation also calls these helpers, and its result does not change: it re-wraps the error as INVALID_ECL as before.

Tests. 13 new tests, all of which fail on main:

  • tests/cs/cs-snomed.test.js: 9 tests, one per operator, plus in with a known concept followed by an unknown one. Each test checks for a 400 issue with this code, tx-issue-type and text.
  • tests/tx/expand-snomed-whole.test.js: 4 tests. Each runs $expand over HTTP for in (an unknown refset), is-a, = and descendent-of, expects 400, and checks that the issue matches the one << X in ECL gives.

Results with this change:

  • tests/tx without test-cases: 1356 passed.
  • tests/tx/test-cases.test.js: 5182 passed.
  • tests/cs: 1483 passed. 4 failed, and the same 4 fail on unchanged main in the same environment (3 LOINC external-mapping tests from a stale local test database, and 1 RXNATOMARCHIVE read-only test).

🤖 Generated with Claude Code

A ValueSet filter such as concept in 41000147108 or concept is-a
584021000052104, naming a concept the edition does not have, threw a plain
Error, so $expand answered 500 (exception / invalid-data). The concept filter
helpers (=, is-a, descendent-of, child-of, generalizes, descendent-leaf,
is-not-a, in) now throw a 400 OperationOutcome issue, error / invalid /
vs-invalid, with the same "The SNOMED CT Concept X is not known" text. This
is the same form an unknown concept in ECL already gets (tx-ecosystem
snomed-expand-ecl-unknown-concept).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@grahamegrieve

Copy link
Copy Markdown
Contributor

How I feel about this depends on https://chat.fhir.org/#narrow/channel/437028-Terminology-Service-Test-Cases/topic/Filter.20on.20an.20invalid.20Conceptwhat/with/638487832.

There is not consistency on this form FHIRsmith or in the test cases, and there should be, but there's two possible outcomes: silently drop the invalid code wherever it is found, or make it an error.

I favour silently dropping it, but will see based on the discussion

@grahamegrieve

Copy link
Copy Markdown
Contributor

I think this is superceded by #396 now

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants