Skip to content

Return 400 for out-of-range _lastUpdated - #5819

Open
Rachit Shrivastava (v-rachitsh) wants to merge 4 commits into
mainfrom
personal/v-rachitsh/bug204940
Open

Rachit Shrivastava (v-rachitsh) wants to merge 4 commits into
mainfrom
personal/v-rachitsh/bug204940

Conversation

@v-rachitsh

Copy link
Copy Markdown
Contributor

Description

Fixes IcM 848848621 (FHIR001 – HTTP Internal Error threshold reached).

GET /Patient?_lastUpdated=le9999-12-31T23:59:59.9999999 returned a 500.

LastUpdatedToResourceSurrogateIdRewriter converts _lastUpdated predicates
into ResourceSurrogateId predicates. Because surrogate IDs only carry
millisecond resolution, <= T is rewritten as < trunc(T) + 1ms. For values
in the last millisecond of DateTime.MaxValue, that addition throws
ArgumentOutOfRangeException from DateTime.AddTicks. Separately, because the
surrogate ID left-shifts ticks by 3 bits, IdHelper.ToId can only represent
datetimes up to ~year 3654 and throws via EnsureArg.IsLte beyond that.

Neither exception is mapped in OperationOutcomeExceptionFilterAttribute, so
both surfaced as 500s and counted against the FHIR001 internal-error monitor.

Changes

  • LastUpdatedToResourceSurrogateIdRewriter now validates the incoming value
    against MaxSupportedLastUpdated and throws BadRequestException (400)
    before the arithmetic can overflow. The bound reserves one millisecond of
    headroom below IdHelper.MaxDateTime so the +1ms rounding stays
    representable.
  • New LastUpdatedValueOutOfRange resource string naming the max value.
  • Unit tests covering all four operators past the bound and at the bound.
  • E2E tests (SQL only) covering the ICM repro plus in-range regression guards.

BadRequestException was chosen deliberately: InvalidSearchOperationException
maps to 403, not 400.

Affected queries

All of these returned 500 and now return 400:

  • _lastUpdated=le9999-12-31T23:59:59.9999999 (the ICM repro)
  • _lastUpdated=le9999-12-31 (date-only End expansion)
  • _lastUpdated=9999-12-31 (eq range upper bound)
  • _lastUpdated=gt|ge|lt9999-12-31T23:59:59.9999999
  • _lastUpdated=gt5000-01-01T00:00:00Z (surrogate-ID ceiling, ~year 3654)

Cosmos DB is unaffected — it filters on lastUpdated directly.

Related issues

Addresses AB#204940.

Testing

Describe how this change was tested.

FHIR Team Checklist

  • Update the title of the PR to be succinct and less than 65 characters
  • Add a milestone to the PR for the sprint that it is merged (i.e. add S47)
  • Tag the PR with the type of update: Bug, Build, Dependencies, Enhancement, New-Feature or Documentation
  • Tag the PR with Open source, Azure API for FHIR (CosmosDB or common code) or Azure Healthcare APIs (SQL or common code) to specify where this change is intended to be released.
  • Tag the PR with Schema Version backward compatible or Schema Version backward incompatible or Schema Version unchanged if this adds or updates Sql script which is/is not backward compatible with the code.
  • When changing or adding behavior, if your code modifies the system design or changes design assumptions, please create and include an ADR.
  • CI is green before merge Build Status
  • Review squash-merge requirements

Semver Change (docs)

Patch|Skip|Feature|Breaking (reason)

@v-rachitsh Rachit Shrivastava (v-rachitsh) added Bug Bug bug bug. Azure API for FHIR Label denotes that the issue or PR is relevant to the Azure API for FHIR Azure Healthcare APIs Label denotes that the issue or PR is relevant to the FHIR service in the Azure Healthcare APIs No-PaaS-breaking-change No-ADR ADR not needed labels Sep 14, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Azure API for FHIR Label denotes that the issue or PR is relevant to the Azure API for FHIR Azure Healthcare APIs Label denotes that the issue or PR is relevant to the FHIR service in the Azure Healthcare APIs Bug Bug bug bug. No-ADR ADR not needed No-PaaS-breaking-change

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant