Repository navigation
Validate Table Edm.DateTime writes and preserve legacy reads - #2870
Open
Justin Adler (PureKrome) wants to merge 2 commits into
Open
Justin Adler (PureKrome) wants to merge 2 commits into
Justin Adler (PureKrome) wants to merge 2 commits into
Conversation
Reject Edm.DateTime property values outside the range Azure Table Storage supports (1601-01-01T00:00:00Z to 9999-12-31T23:59:59.9999999Z) or not in an accepted ISO 8601 format, returning 400 InvalidInput on insert, update, merge, upsert and batch writes. Reads of out-of-range values persisted by earlier Azurite versions keep working. https://learn.microsoft.com/en-us/rest/api/storageservices/understanding-the-table-service-data-model#property-types https://learn.microsoft.com/en-us/rest/api/storageservices/formatting-datetime-values Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Contributor
There was a problem hiding this comment.
🟡 Changes recommended
Date-only normalization and strict legacy-read validation can make persisted entities unreadable.
2 open issues
What changed in this PR
Extends Table property validation to reject unsupported Edm.DateTime writes, following the existing Edm.Int64 approach.
Changes:
- Adds format, calendar, and UTC range validation.
- Shares the range-validation flag across numeric and date properties.
- Adds unit and REST coverage plus release notes.
| File | Description |
|---|---|
| tests/table/unit/serialization.unit.test.ts | Tests date boundaries, formats, and legacy serialization. |
| tests/table/apis/table.validation.rest.test.ts | Tests write rejection and legacy reads. |
| src/table/entity/NormalizedEntity.ts | Generalizes the range-validation flag. |
| src/table/entity/EntityProperty.ts | Passes validation settings to DateTime properties. |
| src/table/entity/EdmDateTime.ts | Implements date format and range checks. |
| ChangeLog.md | Documents the Table validation change. |
Review effort: Balanced
…ormat checks on reads
Justin Adler (PureKrome)
force-pushed
the
fix/table-edm-datetime-range
branch
from
October 21, 2026 06:44
511bd75 to
9268d03
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

👋🏻 G'day Azurite team. I didn't make an issue because I don't have a question but found what i believe is a bug. I'm not sure if that is against the contributor's agreement (I did read it and could see anything that jumped out at me). If it's wrong, i can add an issue, etc.
This PR fixes Azurite denying "invalid"
Edm.DateTimevalues so it's exactly like (production) Azure Table Storage. This prevents developers having code that works against Azurite and then explodes against ATS.Table: reject
Edm.DateTimevalues that Azure Table Storage doesn't support📖 The rules (official Microsoft docs):
YYYY-MM-DD,YYYY-MM-DDThh:mm<TZDSuffix>orYYYY-MM-DDThh:mm:ss[.f{1,7}]<TZDSuffix>. The suffix is optional; it is eitherZor an offset between-23:59and+23:59.This follows the same approach as #2805, which fixed the same kind of problem for
Edm.Int64(#2558).The problem
Azurite accepts any string as an
Edm.DateTime, including dates before 1601 and text that isn't a date. Real Azure rejects these.A common way to hit this: a .NET app leaves a
DateTimeproperty at its default value,DateTime.MinValue(0001-01-01T00:00:00.0000000Z). Tests pass against Azurite and then fail against Azure.Before and after
Edm.DateTime0001-01-01T00:00:00.0000000ZDateTime.MinValue, too earlyInvalidInput1600-12-31T23:59:59.9999999ZInvalidInput1601-01-01T00:00:00.0000000Z9999-12-31T23:59:59.9999999Znot-a-dateInvalidInput0001-01-01…via upsert (PUT)InvalidInputWhat changed
src/table/entity/EdmDateTime.ts:validate(value, validateRange = true)now checks:2023-02-29and24:00are rejected. Otherwise it throwsTypeError.1601-01-01T00:00:00Zup to the end of9999-12-31. Otherwise it throwsRangeError.EntityProperty.ts/NormalizedEntity.ts: the existingvalidateInt64Rangeflag from Validate Table Edm.Int64 writes and preserve legacy reads #2805 is renamed tovalidateRangeand now applies to DateTime too.400 InvalidInput.TableHandleralready reads withnew NormalizedEntity(entity, false)(added in Validate Table Edm.Int64 writes and preserve legacy reads #2805). Out-of-range dates that older Azurite versions saved to a local database still read back fine.Try it yourself
The script below has no dependencies and needs Node 18+. It sends raw REST requests using Azurite's well-known dev account. Save it as
edm-datetime-repro.mjs.edm-datetime-repro.mjs1. Before: the released Azurite (3.37.0) accepts the bad values
2. After: this branch rejects them
git fetch https://github.com/PureKrome/Azurite.git fix/table-edm-datetime-range git checkout FETCH_HEAD npm ci --legacy-peer-deps npm run build node dist/src/table/main.js --location ./tmp-azurite # leave this running; run the script from a second terminal node edm-datetime-repro.mjs3. Run the tests
Tests added
tests/table/unit/serialization.unit.test.ts: boundary values, time-zone offsets, malformed strings, UTC handling, and reading old out-of-range data.tests/table/apis/table.validation.rest.test.ts: insert and upsert return400 InvalidInput; the min and max return201; an old out-of-range value saved directly to the database still reads back through both GET paths.srcchanges, 4 of the new tests fail.npm run lint,npm run build,npm run test,npm run test:tableandnpm run test:table:in-memoryall pass.This PR returns
400 InvalidInputfor out-of-range dates, the same as #2805 does for Int64. I couldn't confirm the exact code real Azure returns today - I wasn't sure what to really use here. The only real error response I found is older (2012). It showsOutOfRangeInput("One of the request inputs is out of range.") forDateTime.MinValue: http://www.anujchaudhary.com/2012/10/azure-table-storage-one-of-request.html. If a maintainer can confirm Azure still returnsOutOfRangeInput, I'm happy to change it.Checklist
mainChangeLog.mdupdated under "Upcoming Release" › "Table:"