---
title: Empty Is Not Zero
type: anti-pattern
level: L2
status: live
revision: 1
updated: 2026-08-14
systemVersion: 4.2
tags: [data, analysis, verification]
rating: 8.85
ratingAxes: useful 9 · evidence 9 · pull 9 · original 8 · form 9
ratingKind: derived
source: pattern log PAT-059, 2026-08-03
---

# Empty Is Not Zero

_Written 2026-08-14 · last verified 2026-08-14 · system v4.2 · live_

**TL;DR** — An export did not run over a weekend, so three daily files were byte-identical and one day showed 59 in revenue against a normal 130 to 368. The analysis read a pipeline outage as a demand collapse, in the exact window a spend cut was being evaluated. A blank cell and a real zero look the same.

## Pattern

You compare a metric across time. One period is dramatically lower. You explain the drop — a campaign ended, a channel cooled, a competitor moved.

The source did not run that period. The row is blank, and blank renders as zero.

## Why it looks right

The table is complete. Every date has a row and every row has a number, because the loader helpfully filled the gap. Nothing in the output distinguishes *nobody bought anything* from *nobody measured anything*.

The explanation you reach for is usually plausible, which is what makes it dangerous. A real cause is available, so the missing data never gets suspected.

## Why it fails

The two readings imply opposite actions. A genuine collapse means intervene; a failed export means fix the pipeline and re-run the analysis. Choosing between them by looking at the number alone is impossible.

It gets worse when the outage overlaps a deliberate test. In one case the missing weekend sat exactly inside the window where a marketing spend cut was being evaluated — the outage would have been read as evidence that the cut worked.

## Instead

**Check that the source ran before comparing what it says.** File modification time, byte size, row count — three cheap signals, none of which require reading the data:

> three consecutive daily exports byte-identical → the job did not run, the days are not zero

Then treat the freshest data as provisional. Measured on one pipeline: the export day itself was incomplete by about 42%, the day before by 7%, and only by two days back did the gap fall under 1%. **The last two days of an export never belong in a comparison window** — not because they are wrong, but because they are still arriving.
