Data Watch · August 9, 2026

One Line of Date Parsing Made Every Region Look Normal

Two days ago we retracted a set of drought percentages that came from a hard-coded function of a Pacific index. In doing that we said our own rainfall feed was not trustworthy either, and promised to say why. Here is why. A single guard clause, true for every month of the year, made the code read the day of the month as the month. The comparison baseline collapsed to one earlier day. The feed is now rebuilt, and all eight regions are reporting monthly anomalies against multi-year baselines: ten years for seven regions, and the seven years currently available for East Africa.

By Christopher W. Corwin · IAMElNino.com · 10 min read
← All Posts

On 7 August we published a correction retracting seven regional drought percentages that had gone out to subscribers. Those figures came from a step function of the Oceanic Niño Index with no rainfall data in it at all.

In the same post we said something less comfortable: the observed rainfall feed we were checking them against could not be trusted either. Every region read NEAR NORMAL, including one at −94 percent and one at +16,142 percent. We flagged the panel as under repair and promised the diagnosis. This is it, along with the numbers the feed now produces.

1
Days in the "climatology" the old code compared against
29
Month index the parser computed for 30 June
10
Years in the baseline now, for seven of eight regions

The Line

ClimateSERV returns dates as MM/DD/YYYY. Our worker extracted the month like this:

const m = p.length===3 && parseInt(p[0])<=31 ? parseInt(p[1])-1 : parseInt(p[0])-1;

Read the guard. Months are 1 to 12, so parseInt(p[0]) <= 31 is true for every month there is. The condition can never be false. So the expression always takes the first branch and returns p[1], which is the day.

For 06/30/2026 it computed month index 29. For 05/30/2026 it also computed 29, because both fall on the 30th.

What That Did to the Baseline

The code then gathered "all other granules in the same month" to average as a climatology. But since the month had become the day number, "same month" meant "same day number".

The request window was about 61 days, 1 May to 30 June 2026. Across 61 days there is exactly one other granule numbered 30: 30 May.

IAMElNino.com analysis. So the field labelled climatology_mm held the rainfall on a single day, one month earlier. The "anomaly" was 30 June minus 30 May. We reconstructed the series and ran the worker's own expression against it, and it reproduces every published figure exactly: +0.5, +4.9, −4.9, −0.6, +1.5, +2.6, −4.0 and −2.4 mm.

Three consequences followed, and together they explain everything readers were seeing.

The Fix We Nearly Shipped

The obvious repair is to ask ClimateSERV for monthly sums instead of daily averages. We wrote that patch: change intervaltype from 0 to 1, and operationtype from 5 to 4.

Before deploying it we tested the parameters against the live API. That patch would have broken the feed completely.

intervaltypeoperationtypegranules returned
0 (daily)5 (average)91
0 (daily)4 (sum)0
1 (monthly)4 (sum)0
0, 1, 2, 34 (sum)0 for all

IAMElNino.com analysis, from live calls to the ClimateSERV API on 9 August 2026 between roughly 14:00 and 14:30 UTC, using a one-degree test polygon and a January to March 2024 window. For CHIRPS, the only combination that returns data is daily granules with a spatial average. Ask for a sum and ClimateSERV returns an empty array with progress 100 and no error. Ask for monthly and it does the same.

ClimateSERV's own documentation lists operation type 4 as "Sum" in its getParameterTypes response. For CHIRPS it does not honour it. The interval enumeration is not documented at all: the docs say it is "hardcoded in the mark up language of the current client".

Had we deployed that patch, the parser would have thrown "Empty data response" for every region, the feed would have gone dark, and we would have published a post saying it was repaired. The test took ten minutes.

What the Rebuilt Feed Does

The aggregation had to move into our worker rather than the request. Each granule is the spatial mean rainfall for one day in mm, so summing across a calendar month gives the monthly areal-mean total. The baseline comes from the same calendar month in prior years, fetched as separate requests and cached unless the source dataset or processing method changes.

Before and After

Same eight regions, same day, same underlying CHIRPS rainfall product, which combines satellite estimates with station observations. The left side is what the site served on the morning of 9 August. The right side is what it serves now.

RegionOld: value vs "baseline"Old labelNew: June 2026 total vs June normalNew labelYears
South Asia / India7 vs 7 mm (+7%)NEAR NORMAL98 vs 116.4 mm (−15%)NEAR NORMAL10
Northern China5 vs 0 mm (+16,142%)NEAR NORMAL81 vs 92.9 mm (−13%)NEAR NORMAL10
Northeast Brazil0 vs 5 mm (−94%)NEAR NORMAL34 vs 36.9 mm (−8%)NEAR NORMAL10
Southern Africa0 vs 1 mm (−93%)NEAR NORMAL9 vs 6.9 mm (+31%)ABOVE NORMAL10
Eastern Australia2 vs 1 mm (+267%)NEAR NORMAL32 vs 27.3 mm (+18%)NEAR NORMAL10
Indonesia & SE Asia9 vs 7 mm (+39%)NEAR NORMAL189 vs 240.2 mm (−21%)NEAR NORMAL10
Peru & Ecuador coast0 vs 4 mm (−92%)NEAR NORMAL98 vs 137.9 mm (−29%)MODERATE DEFICIT10
East Africa (Horn)1 vs 3 mm (−71%)NEAR NORMAL36 vs 52.9 mm (−32%)MODERATE DEFICIT7

India is the clearest illustration of why nobody caught this. Seven against seven looks like a reading. It was one day against one day, and the fact that they nearly matched made it look like a region sitting comfortably at its normal. The real comparison is 98 mm of June rain against a 116.4 mm June average across ten years, 2016 to 2025.

Southern Africa illustrates why the new percentage guard matters. Its June baseline is only 6.9 mm, because June is deep in its dry season, so even a small absolute difference can produce a large percentage anomaly. It now returns +31 percent, a sensible statement about a dry month that was slightly wetter than usual. The earlier +16,142 percent occurred in Northern China, where the broken one-day baseline was approximately 0.03 mm.

What the Numbers Actually Say

Three regions show deficits exceeding 20 percent for June 2026: Indonesia and Southeast Asia at 21 percent below its ten-year June average, the Peru and Ecuador coast at 29 percent below, and East Africa at 32 percent below its seven-year average. Peru is worth noting because it is the site's designated flood region: the canonical El Niño signal on that coast is heavy rainfall, not dryness. India, Northern China and Northeast Brazil also sit modestly negative, between 8 and 15 percent below average.

Set against the alert we retracted, the picture is close to inverted. India was emailed at 78 percent drought risk and is 15 percent below normal, which is unremarkable. Southern Africa was emailed at 65 percent and came in wetter than usual. Indonesia and Southeast Asia was emailed at 80 percent and is the one large region genuinely dry, at −21 percent, which the ladder got right by accident rather than by measurement.

One caution on all of it. June is a single month, and for several of these regions it is not the month that matters. Southern Africa's rains do not begin until October, so a June reading there says almost nothing about the season FEWS NET is actually worried about. A monthly anomaly is an observation, not a seasonal outlook.

The testable version: the claim is that the feed now measures what it says it measures. Three checks with dates attached. First, the observation period should advance from June 2026 to July 2026 within roughly the next four weeks, since observed availability through this particular ClimateSERV endpoint has been running roughly 40 days behind, and July closed on the 31st. If it is still reporting June in mid-September, the month-completeness logic is stuck. Second, East Africa should reach a ten-year baseline like the others as the backfill finishes; if it stays at seven, ClimateSERV does not hold those years for that polygon and we will say so. Third, and most importantly, no region should ever again publish a percentage against a baseline under 5 mm. Note that the drought panel this feed fed has since been withdrawn from the dashboard entirely, pending independent validation of the rebuilt figures; see the correction. If it returns and you see a three-figure or four-figure percentage on it, the guard has failed and we want to know. The feed states baseline_n for every region so you can check the evidence depth yourself.

What to Watch

The Short Version

A guard clause that could never be false made a date parser read the day as the month. That turned a climatology into a single earlier day, turned percentages into divisions by near-zero, and pushed every region into the same label because the thresholds assumed a different unit. None of it threw an error, which is why it survived.

The repair is deployed and all eight regions now report monthly totals against a real multi-year baseline. We also nearly shipped a fix that would have silently emptied the feed, and only caught it because we tested the API parameters instead of trusting the documentation. That is the more useful lesson of the two.

Data vintage. Figures in this article are those published as of 9 August 2026, and the article has not been rewritten to match later data. NOAA revises weekly Niño-region values each Monday and can revise recent seasonal RONI and ONI values for up to two months after first posting. Where a number here differs from the live dashboard, the dashboard carries the newer figure.

Sources

← All Posts Teleconnections Dashboard →