Proposal: Opt-in case-insensitive matching for FHIR status code enums (e.g., “Active” vs “active”)

21 views
Skip to first unread message

Donald Wheeler

unread,
Feb 10, 2026, 1:53:03 PM (7 days ago) Feb 10
to HAPI FHIR

Hi HAPI FHIR community,

We’re evaluating HAPI FHIR to implement FHIR-based payer connectivity at our organization, and we’ve run into a pragmatic interoperability issue that I’d like feedback on before proposing a PR.


What we’re seeing (concrete example)

From a payer JSON response payload sample, we’re receiving a ClaimResponse resource with:

JSON
"status": "Active"
but the base FHIR specification defines that status code as "active" (lowercase). Meaning is clear, but casing is non-conformant.

In HAPI this currently fails during parsing - specifically in the enum mapping fromCode method where the incoming string is matched using a direct string equality comparison (so "Active" does not map to active).

So far, I’ve only observed this particular case on ClaimResponse.status, but it feels like a “canary in a coal mine”: once we start integrating broadly, we expect to encounter similar capitalization issues on other enum-coded fields.


Acknowledging the standards concern (up front)

We absolutely agree the correct fix is for partners to send conformant FHIR. We also understand why HAPI should remain strict by default, accepting nonconformant content can hide data quality issues and reduce pressure on implementers.

In our case, we would still treat this as a partner defect and push for correction; the goal is to avoid blocking connectivity while remediation is in progress.


Proposal: strict-by-default, opt-in relaxed behavior

Would the community be open to a configurable (opt-in) feature that allows case-insensitive matching when parsing known enum-backed code values, so that "Active" maps to the existing enum value active?

Key goals:

  • No behavior change by default (strict remains the default).
  • When enabled, behavior is limited to case normalization during parsing for enum-coded values (not “accept anything”).
  • Parser-only: the intent is explicitly not to change persistence, indexing/search behavior, or canonical serialization — only to accept nonconformant casing at ingest time.
  • Documented clearly as a non-standard interoperability workaround.
  • Backed by unit tests verifying strict mode continues to reject incorrect casing when the option is disabled.

A strawman name might be something like:
enableCaseInsensitiveEnumCodeMatching (name totally negotiable).


Scope questions (where I’d like guidance)

Before I write code, I’d love community/maintainer input on scope and design direction:

  1. Would an opt-in “case-insensitive enum code parsing” feature be acceptable in principle?

  2. If yes, what scope would be most appropriate?

    • Narrow: only apply to resource .status fields (where many are enumerations), OR
    • Broader but still controlled: apply to enum-backed code parsing generally (still only on parsing), OR
    • Alternative preferred approach: e.g., interceptors / pre-processing recommendations instead of core behavior.
  3. Where would you prefer this configuration to live (high-level guidance is enough):

    • on FhirContext / parser configuration,
    • on validation configuration,
    • or elsewhere?
I’m happy to do the work

If this direction is acceptable, I’m prepared to:

  • implement the change,
  • add tests for strict vs opt-in behavior,
  • document it prominently as a non-conformant interoperability option,
  • and follow through on any feedback or resulting issues.

If helpful, I can provide a minimal reproducible example (resource + current exception/failure location) and a proposed test case layout.

Thanks in advance for any guidance, and for all the work you all do on HAPI FHIR.

-- Donald Wheeler

James Agnew

unread,
Feb 11, 2026, 3:21:15 PM (6 days ago) Feb 11
to Donald Wheeler, HAPI FHIR
Hi Donald,

For what it's worth, I think this is a good idea.

Intuitively I don't love the idea of being lenient here given that the elements we're talking about are such fundamental ones (Patient.gender, Observation.status, etc) but I think you could very much make the argument that despite differences in case (e.g. "Cancelled" vs "cancelled"), it's still very clear what the intent of the resource's author was. 

And we do have a bunch of other cases where we're similarly lenient. E.g. in JSON parsing for boolean values we accept quoted strings and ignore the casing, we allow a single quoted string instead of an array for repeating elements, etc.

In terms of the implementation, honestly I don't actually think this even needs a new config flag. Our general pattern here has always been to make sure that we emit an error to the IParserErrorHandler when we encounter a recoverable parse error, and let it decide whether the error should be fatal or not. I'd propose that the new logic for handling bad casing needs to be in ParserState.PrimitiveState#attributeValue - The trick would be to detect that the underlying datatype rejected the value, then determine that it is an enumeration and figure out if a same-but-different-case value exists for that enumeration. If it does, an error could be emitted to the IParserErrorHandler, and the corrected value could be placed in the datatype.

Cheers,
James

--
You received this message because you are subscribed to the Google Groups "HAPI FHIR" group.
To unsubscribe from this group and stop receiving emails from it, send an email to hapi-fhir+...@googlegroups.com.
To view this discussion visit https://groups.google.com/d/msgid/hapi-fhir/fd9f061d-a357-405f-a168-03151dd2b673n%40googlegroups.com.

Donald Wheeler

unread,
Feb 12, 2026, 9:10:18 AM (6 days ago) Feb 12
to HAPI FHIR

Hi James,

Thank you; I really appreciate the thoughtful take, and the comparison to other places where HAPI is already pragmatically lenient.

I’m going to look closely at your suggested approach in ParserState.PrimitiveState#attributeValue (detect rejection → confirm enum → find same-but-different-case value → recover). That makes sense and fits the existing “recoverable parse error” pattern you described.

That said, I’d like to counter‑propose an even more direct option:

Loosen the enum matching at the source, i.e., in the generated fromCode(String) methods where we currently do direct string equality.

Two options:

  • equalsIgnoreCase(...), or
  • (my preference for explicitness, even if less syntactically correct in modern IDEs) normalize both sides and compare, e.g. toLowerCase().equals(...)

Why I like this approach:

  • Bad casing never makes it into the datatype (no post‑facto correction needed).
  • The change is tiny and localized (one enum, one method, one comparison).
  • It’s exercised only when that specific value is parsed so it’s narrow in runtime impact.
  • It is clear what is being done to the input and why

If you think enum-level relaxation is acceptable, I can put together a small PR with tests showing strict behavior isn’t impacted beyond this casing tolerance.

Happy to follow the IParserErrorHandler recovery approach if that’s the preferred direction; I just wanted to float this simpler alternative first.

Cheers,
Donald Wheeler

James Agnew

unread,
Feb 12, 2026, 9:21:54 AM (6 days ago) Feb 12
to Donald Wheeler, HAPI FHIR
Truthfully I don't like the idea of loosening the structures themselves as much:

- If the enumerations themselves are relaxed, we don't have any way to detect and react to the fact that they're parsing invalid data, they'll just silently accept it. 
- We can't even configure the parser to reject these values, a full validator would be needed which is much more expensive than the parser error handler.
- This is also a -much- harder fix to implement since it means touching the code generator which generates these structures

The thing I like about my proposed approach is that it respects our general tendency to honour Postel's law (be forgiving in what you accept), but it also means that anyone with this kind of casing problems is going to have a very noisy error log by default, and will be incented to do something about that.

Cheers,
James

Donald Wheeler

unread,
Feb 12, 2026, 1:16:59 PM (5 days ago) Feb 12
to HAPI FHIR
Copy that, James. Building something for this rn. A question about the logic flow - should the StrictErrorHandler still throw an exception, or should I build it to be noisy vis a vis logging but NOT do a "myErrorHandler.invalidValue(location, value, e.getMessage());" that will cause this if it's able to recover and populate the enum successfully?

James Agnew

unread,
Feb 12, 2026, 2:33:42 PM (5 days ago) Feb 12
to Donald Wheeler, HAPI FHIR
StrictErrorHandler should throw an exception IMO

Donald Wheeler

unread,
12:18 PM (11 hours ago) 12:18 PM
to HAPI FHIR
PR is up for this proposal, James https://github.com/hapifhir/hapi-fhir/pull/7566 in case anyone is curious
Reply all
Reply to author
Forward
0 new messages