Logbook · Entry 02Data validation4 min read

Seven forecast-data failures that passed parsing

Seven times, a forecast payload arrived looking like success: HTTP 200, decoded cleanly as GRIB or GeoTIFF, values a chart could draw. Seven times it was wrong anyway — about the place, the direction, the time interval, the model, or the run state. Parsing proved each payload was readable; it took an independent witness to prove what it actually represented.

Every incident below has the same anatomy: what arrived looking fine, the witness that disagreed, and the rule the platform keeps. The atlas pairs them; the cases follow.

Seven forecast-data failures and their independent checks

A payload can parse cleanly while still representing the wrong place, vector, time window, model, or run.

Seven observed provider-data failures, each paired with the independent check that exposed it.

  1. 01Misregistered WCS cropCompare crop samples with an independent point query.
  2. 02Successful zero-filled subsetTest physical plausibility: afternoon heat cannot be zero everywhere.
  3. 03Grid-relative wind left unrotatedRead projection metadata; rotate vectors; compare bearings.
  4. 04Wrong or truncated model objectVerify Content-Length, ETag, and grid geometry.
  5. 05Flux window treated as instantaneousInspect GRIB time-range metadata and sequences across resets.
  6. 06Partially published model runRequest the final required forecast hour before building.
  7. 07Stale provider identifierQuery live capabilities or the provider directory.
Incidents observed during model-feed verification through 2026-08-08.Units Diagnostic relationships; no numeric scale

A WCS crop sampled the wrong cells

Arrived

A correctly shaped terrain crop at the requested “native” resolution. The sampled RDPS elevation — 1,426 geopotential metres — was a perfectly plausible number for a mountain site.

Witness

GeoMet's point query reported 1,168 gpm for the same model cell, and 2 m temperatures differed by up to 2.5 °C at half the test sites. A finely oversampled crop reproduced the point values — the fault was the crop's sampling, not the model.

While the pipeline read WCS, the builders compared several crop values with an independent point query before trusting the georeferencing. The transport is retired; the rule is not.

Rule

A crop is a rendered coverage, not proof of nearest-cell sampling.

A broken WCS request returned valid zeros

Arrived

DescribeCoverage advertised `long` and `lat` axes. Subsetting with those names returned HTTP 200 and a valid GeoTIFF — filled entirely with zeros.

Witness

Zero sensible heat flux on a sunny afternoon implies no convection across the entire crop. That is not weather; it is a broken request. The shape actually required the undocumented `x`/`y` axes and an explicit `SUBSETTINGCRS=EPSG:4326`.

As true of a decoded GRIB field as of a rendered crop — and the same distinction the contract keeps on the wire:

Zero is a value; absence is a capability statement

A decoder must preserve the difference between a supported field that reports zero and a field the source does not publish.

Missing capability is not measured zero. This Meteogram shows one atmospheric profile in Etc/UTC. An unsupported gust field is absent, while supported precipitation is present and explicitly zero. All 6 hours explicitly publish precipitationMmHr as zero. No hour carries windGustMps, and the scenario capability declares gust false.

Field present

precipitationMmHr: 0

12:000.013:000.014:000.015:000.016:000.017:000.0

Interpretation: the source supports this quantity and reports none.

Field absent

windGustMps is not in the document

Interpretation: the source does not publish gust, so its value is unknown.

The two states come directly from the validated scenario document. A missing windGustMps field is never replaced with 0 m/s.Units precipitation mm/h · gust m/s when published

Rule

Check physical plausibility wherever zero can mean either a measurement or a broken request.

Grid-relative winds were not rotated

Arrived

U and V components decoded normally and produced realistic wind speeds.

Witness

Speed is exactly the property rotation preserves, so a believable magnitude vouches for nothing about direction. In one REPS verification, the unrotated member read 261° where the transformed value was 236.6° — bracketed by deterministic forecasts at 250° and 238°. HRRR errors at these longitudes ran 10–15°.

HRRR’s Lambert grid and REPS’s rotated latitude–longitude grid define their components along grid axes rather than true east and north. The rotation was checked three ways — ecCodes geolocation to about 10⁻⁶ degrees, member-for-member speed against GeoMet, and directional comparison with sibling models — and the builders now read each grid’s vector convention from GRIB projection metadata before deriving direction.

A plausible speed can still point the wrong way

Vector components become meteorological direction only after their grid convention and projection are resolved.

Four-stage validation chain: decode plausible U and V components; read the grid-relative convention from projection metadata; rotate into true east and north; compare the resulting bearing with independent geolocation and sibling-model witnesses. In the recorded REPS check, 261 degrees grid-relative became 236.6 degrees true.

  1. 01

    Parsed payload

    U and V decode

    The component magnitudes produce a realistic wind speed.

  2. 02

    Projection metadata

    Grid axes ≠ true axes

    Lambert and rotated-latitude grids declare the component convention.

  3. 03

    Required transform

    Rotate before direction

    Resolve the vector into true east and north, then derive bearing.

  4. 04

    Independent witness

    261° → 236.6°

    ecCodes geolocation and sibling forecasts bracket the corrected REPS direction.

What the second witness changes: A correct wind magnitude is compatible with an incorrect bearing because rotation changes direction without changing speed.

REPS and HRRR checks as recorded during model-feed verification, through 2026-08-08 — a dated record. Rotation preserves magnitude, so speed alone cannot witness direction.Units direction degrees true · geolocation comparison degrees

Rule

A correct magnitude does not prove a correct direction.

A model URL returned another model’s grid

Arrived

A GEPS orography URL returned 4.3 MB of decodable GRIB.

Witness

The grid inside was REPS-shaped. The one external tell: the body length disagreed with the server's declared Content-Length and ETag. An immediate retry returned the expected bytes; the upstream cause remains unknown.

The download client now checks every full response against its declared length and retries mismatches.

Rule

A valid file format cannot identify the model inside it.

Flux fields used different time intervals

Arrived

Several models expose sensible heat flux in units reducible to W/m² — the same variable, the same unit, believable values everywhere.

Witness

The shared unit hides three different clocks. HRRR and REPS publish instantaneous values; GFS publishes averages over growing windows that reset every six hours; GEPS publishes accumulations that require differencing. Treat all three as instantaneous and afternoon heating smears into the morning.

The builders read product-definition and time-range metadata, then test sequences across window resets.

One unit can describe three different clocks

A field name and W/m² unit do not say whether a heat-flux value is instantaneous, averaged, or accumulated.

A comparison of heat-flux semantics observed in provider products: HRRR and REPS publish instantaneous values; GFS publishes averages over growing windows that reset every six hours; GEPS publishes accumulations that require differencing. Product-definition and time-range metadata, checked as a sequence across resets, identify the semantics.

  1. 01

    HRRR · REPS

    Instantaneous

    The value describes the product's stated instant.

  2. 02

    GFS

    Growing average

    The averaging window grows, then resets every six hours.

  3. 03

    GEPS

    Accumulation

    Successive products must be differenced over their declared intervals.

  4. 04

    Independent witness

    Inspect the sequence

    Read product-definition and time-range metadata across a window reset.

What the second witness changes: Normalizing units without normalizing the provider's clock can move afternoon heating into the morning while leaving believable numbers.

The builders preserve each provider's declared time semantics before the shared derivation consumes heat flux. Semantics as observed in provider products through 2026-08-08 — a dated record.Units heat flux W/m² · time windows h

Rule

A variable name and unit do not define its time semantics.

A model run was only partly published

Arrived

Early forecast hours for a new cycle downloaded cleanly while the provider was still publishing later hours.

Witness

The final scheduled hour was absent. A build started then would have failed after thousands of requests.

The forecast engine probes the final required forecast hour first.

Rule

A run does not exist until its last expected product answers.

Provider paths changed before their documentation

Arrived

Documentation, examples, and old forum answers all pointed to layer families such as `GDPS.ETA_*`, `RDPS.ETA_*`, and legacy ensemble directory trees.

Witness

The live capabilities and directory listings had moved on: some names returned 404; others survived as aliases with different availability.

The forecast model feed reference records what was live-verified and when.

Rule

Provider identifiers are dated observations; the service outranks its prose.

What parsing can never prove

Schema validation proves shape. Each trust boundary also compares the payload with an independent fact about identity, location, projection, or time semantics — and the check lives beside the code that crosses the boundary.

The provider’s relevant vector warning is explicit in the ECCC RDPS data specification: U and V must be resolved relative to the defined grid. The incident-specific countermeasures live in the builders and shared download clients.