Skip to content

Fix reads of the first chunk when CDS returns it short - #15

Merged
nicolamasotti merged 2 commits into
mainfrom
fix-short-first-chunk-padding
Oct 27, 2026
Merged

nicolamasotti merged 2 commits into
mainfrom
fix-short-first-chunk-padding

Conversation

@nicolamasotti

Copy link
Copy Markdown
Member

What this PR fixes

For some datasets, CDS returns the first request with one time step less than asked. ERA5-Land, for example, has no 1950-01-01 00:00. xarray-ecmwf fills that step with NaN, but got it wrong for every read that doesn't cover the whole first chunk.

Example: ERA5-Land from 1950-01-01, in 75-day requests, shifted by one day:

ds = xr.open_dataset(request, engine="ecmwf", request_chunks={"day": 75}, chunks={})
ds = ds.shift(time=-1)  # the first chunk is read with key 1:75
requested chunk 0:          01-01  01-02  01-03  ...  03-16   75 steps
returned by CDS:                   01-02  01-03  ...  03-16   74 steps

read with key 1:75, expected:     [01-02, 01-03, ..., 03-16]        74 values
                    returned: [NaN, NaN, 01-03, ..., 03-16]         75 values

With request_chunks={"month": 1} or {"year": N}, the same situation raised AssertionError.

Changes

  • get_chunk_values fills the missing step with NaN before taking the requested part of the chunk, not after.
  • No more AssertionError with month and year chunks.

Tests

tests/test_20_client_cdsapi.py simulates a dataset with no 1950-01-01 00:00, without network. It checks partial reads of the first chunk, the shift above, and month chunks. 5 of the 6 tests fail without the fix.

The tests are skipped with xarray < 2025.6, as in the minver-tests job: with zarr 3 installed, those versions can't open anything through the engine. That's an existing problem, to be fixed in a separate PR.

Notes

  • A partial read of the first chunk now decodes the whole chunk, but only when CDS returns it short.
  • All CI jobs pass locally. The integration tests weren't run, as they need CDS credentials.

@alexamici

Copy link
Copy Markdown
Member

Your test case refer to the monthly datasets, but the code was written to fix the EAR5 Land hourly case. Did you check that creating a new hourly dataset starting on 1950-01-01 works with the new code?

@nicolamasotti

nicolamasotti commented Oct 27, 2026 •

Copy link
Copy Markdown
Member Author

No sure why you say that. This tests a fake hourly dataset, not a monthly dataset (they are all fake datasets anyways). I can add more "hours" to the fake request/dataset if you want, but that won't make any difference. I have also tested a real world ERA5-land-hourly ingestion.

Regardless of what happens with a specific "real" dataset, I think the behaviour implemented by this PR should be the default one. Any further concern with specific datasets should be dealt with at a higher level (ingestion level). Anyways at the moment there are none.

@nicolamasotti

Copy link
Copy Markdown
Member Author

I have added more hours of day to the tests that simulate requests to hourly datasets such as ERA5-Land hourly

@nicolamasotti
nicolamasotti merged commit 93ca7ff into main Oct 27, 2026
10 checks passed
@nicolamasotti
nicolamasotti deleted the fix-short-first-chunk-padding branch October 27, 2026 15:41
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