Known problems#
Defects that have been found in this pipeline, and quirks of individual files in the archive that it cannot paper over.
Troubleshooting answers “it printed this error, what do I type”. This page answers “my output looks wrong” and “is the store I already have affected” — the failures that are silent, or that surface a long way from their cause. Each entry says what went wrong, which output it touched, and whether it is fixed.
1. Fixed defects#
1.1 Footprint padding duplicated the footprint’s own edges#
Found and fixed 2026-08-05. Affected every footprint-mode grid built before
that date.
_build_footprint_grid padded outward with range(edge_size), starting at
i = 0 — so the first “padding” cell on each side was
np.max(latitudes) + delta_lat * 0, the footprint’s own edge value a second
time. Two consequences:
A duplicated latitude and longitude in the target grid, sitting at the footprint’s own edges — mid-grid, not at the boundary. Each per-region intermediate inherited whichever duplicate fell inside it, which is what the
Dropping 1 duplicate values in 'longitude'lines in the join log were.One fewer padding cell per side than configured.
edge_size: [100, 100]produced 99 cells of padding, not 100.
No store contains a duplicated row: drop_duplicate_coords removed them during
the join, before anything was written. The lasting effect was the smaller
domain. Padding now starts at i = 1; a clean run prints no Dropping N duplicate values lines at all.
1.2 The target grid was silently truncated to the domain’s regions#
Warning added 2026-08-05. The truncation itself is inherent to how regions are extracted — it is now loud instead of silent.
Extraction interpolates a region onto the whole target grid and then slices
the result to that region’s own bounds ([extract.py][extract-slice]). A target
point that falls outside every region in world_regions_codes therefore lands
in no region file at all and vanishes from the joined domain. Nothing said so:
the log printed
target grid: 384 lat x 308 lon
...
20170101 dataset ready: {'time': 56, 'levels': 20, 'lat': 359, 'lon': 306}
and treated that as success.
For SA, edge_size_lat: [100, 100] pads roughly 23° north of the footprint,
past the northern edge of regions 6 and 9 at 25.078125°N. Twenty-three rows were
dropped from every period. The domain stops at 25.078125°N regardless of what
the config asks for; reaching further north needs regions 2 and 5 added to
world_regions_codes.
build_target_grid now clips the grid to the union of the domain’s regions and
prints a banner naming the regions that would keep the rest, so the grid a run
reports is the grid it writes.
2. File quirks#
Oddities in the files, rather than in this code. They are worth knowing because they break anything that assumes the archive is uniform.
Mk9 and Mk10 cubes do not have the same structure#
The Mk9 .pp cubes and before create dim_0, a bare 0, 1, 2, … index coordinate along time. Nothing creates it
deliberately: _build_time_axis stacks the cube’s forecast dimensions into a
MultiIndex, and one of those dimensions is anonymous in the Mk9 cubes, so it
arrives from DataArray.from_iris named dim_0 and survives the stack as a
leftover level. Mk10 cubes do not have it. dim_0 is now listed in _DROP_VARIABLES in join.py, so no new store gets
one.
The 2014-02-01 15:00 dump carries the previous stamp’s data time#
Every field in the MO201402011500 files has a validity time (t1) of 15:00 but
a data time (t2) of 12:00. Everywhere else the two agree. Iris reads the
mismatch as a three-hour meaning period, so the three time-processed fields
arrive at the interval midpoint, with bounds [12:00, 15:00]:
atmosphere_downward_eastward_stress time=['2014-02-01 13:30:00']
atmosphere_downward_northward_stress time=['2014-02-01 13:30:00']
surface_upward_sensible_heat_flux time=['2014-02-01 13:30:00']
while the other sixteen cubes sit at 15:00. The files themselves are sound: the
gzip is intact, all 374 fields decode, and iris.load returns the full cube set.
It is the whole dump, not one file — tiles 6, 8, 9, 10 and 13 all show it, and
the 12:00 and 18:00 stamps either side are clean. That includes the region-8
file re-archived on 2020-06-27; the later archive date changes nothing, it
carries the same t2.
The pipeline already absorbs this. _restamp_to_interval_end moves a bounded
time point to its interval end, which here is exactly 15:00, putting the averaged
fields back on the shared axis.