Twelve fields. Nine analytical dimensions. Zero information points. And every table rendered correctly.
Last quarter I reviewed a research pipeline that returned a 3,400-word report on a token. Technical section: present. Tokenomics: present. Risk matrix: six categories, all populated. Howey test: four elements, each assessed. The document had headers, sub-tables, confidence tags, a disclaimer, and a five-star scoring table across four dimensions.
It contained not one verifiable fact.
The tells were consistent. Every field read "N/A โ insufficient information." Every risk category read "unknown." The composite risk rating was "unable to assess," which is not a rating. Four dimensions scored zero stars, with a footnote clarifying that the zero referred to the input data, not the asset.
That footnote is the most honest sentence in the entire document. It is also the sentence no downstream system reads.

A report that fails loudly is an asset. A report that fails inside a beautiful template is a liability. The formatting survives the failure. The formatting is what gets consumed.
The contract between two stages
The pipeline had two stages, and the contract between them was clean on paper. Stage 1 extracts information points โ the minimum citable fact units pulled from a source article. Stage 2 runs nine-dimensional analysis, and every conclusion must cite a Stage 1 information point by name. No citation, no conclusion.
Stage 1 returned empty. Not sparse. Empty. Twelve output fields, all default-initialized. The distribution of nulls was uniform across every field, in identical format โ the signature of a template that was never filled, not a partial extraction that collapsed halfway through.
Stage 2 then had exactly two options: throw an error, or fill the frame. It chose the frame. It printed three thousand words of correctly labeled absence and appended a note at the bottom asking a human to supply the missing data. The note was accurate. The note was also on page nine.
There was a second signal, subtler and more damning. Stage 2 had been instructed to "identify the projects and protocols involved" and to "judge source quality." Those are Stage 1's jobs. Field ownership had drifted between the two prompts.
| Failure signature | What it looked like | |---|---| | Uniform nulls across all fields | Template never filled | | Confidence tags on absences | Model confident about nothing | | Downstream-asks-upstream questions | Schema contract drift | | Request for data at page nine | Gate built after the format |
That is not a content failure. That is a contract failure โ two schemas disagreeing about who owns which column, with no integration test between them. The correct fix is four lines of code: feed Stage 2 an empty information-point array, assert that it raises. That test did not exist, because the suite covered the happy path and the near-miss path โ a source with three information points, a source with a paywalled body. Nobody tests the zero.
I have seen this exact failure class before, in a domain where it costs money. In 2017 I manually audited more than forty ERC-20 contracts during the ICO run. A reentrancy bug fails loudly: the funds leave, the balance goes to zero, everyone sees it within the block. An unchecked return value fails silently. The contract keeps running. The state keeps updating. Nothing in the interface says anything is wrong. The difference between those two bugs is not severity. It is observability.
Three mechanics of null propagation
All three are arithmetic, not philosophy.
One: validators check schema, not substance. A JSON validator asked whether "riskLevel": "N/A" is a string will answer yes. It is a perfectly valid string. Null is valid. Empty arrays are valid. The pipeline proceeds because the contract was satisfied โ and the contract was written to describe shape, never to describe sufficiency. Nearly every research pipeline in this industry validates shape.
Two: aggregations treat unanalyzed assets as safe assets. Run ten positions through a portfolio risk model. Nine return a 6 out of 10. One returns N/A. Depending on how you write the reducer, the unanalyzed position either drops out of the denominator entirely โ leaving the average at 6.0 โ or it gets coerced to zero and drags the average to 5.4. Neither outcome is correct. But here is the part that matters: the asset nobody analyzed always looks better than the asset that was analyzed honestly. The blank column is indistinguishable from a clean one, and it is read as clean.
Three: human review skims headers. Nobody reads 3,400 words. They read the tables. The tables are empty, but they are structured, and structure reads as rigor. A risk matrix with six labeled rows and six "unknown" cells looks more thorough than a risk matrix with two rows and two specific findings. It is less thorough by an infinite margin. It also clears review faster.
The same defect shows up at the protocol layer, and this is where I get genuinely irritated. Uniswap V4's hooks make every pool a configurable contract; the hook address is encoded into the pool key itself. Most users never read it. They read the fee tier and the token pair. A blank field where the security assumption actually lives is the identical bug wearing a different jacket โ the audit field is present, the audit field is empty, and the interface renders anyway. Complexity did not create this problem. Complexity just gave the blank more places to hide.
I have one rule about this, and I wrote it down after May 2022. When TerraUSD depegged, my exit protocol executed in minutes and moved everything into BTC and fiat. The reason it worked was not that I was smarter than the market that week. The reason it worked was that the rule had been coded in 2020, before the data turned ambiguous, and the rule had no "if data unavailable, hold" branch. Any rule with a null branch is not a rule. It is a preference with a deadline.

Now scale that up. Tether holds roughly seventy percent of the stablecoin market. Its reserves have never been subjected to a genuinely independent audit. That is a report with a blank attestation field, consumed by an industry that has collectively decided the blank is fine โ not because anyone verified it, but because the schema is valid and the ticker is stable. This is null propagation at a denominator measured in hundreds of billions. Nobody flags it. Flagging it makes you the tedious person at the party.
Volume screams, but liquidity whispers the truth. Every exchange publishes volume, because volume is a complete field โ it always has a number in it. Liquidity depth is usually incomplete, because depth requires a book snapshot, a timestamp, and a stated methodology. Guess which one makes it into the pitch deck.
Hallucination is loud. Null is silent.
The industry's current anxiety is misplaced. Everyone is worried about hallucination โ the model inventing a fifty-million-dollar TVL that does not exist.
Hallucination is loud. Hallucination has a falsification path. Someone opens the block explorer, checks the contract balance, finds four million, and files a bug. The invented number dies within a week because it made a claim, and claims can be killed.
Null has no falsification path. "N/A" cannot be wrong. It cannot be disproven, cannot be contradicted by on-chain data, cannot be embarrassed by a later filing. It survives every audit precisely because it asserts nothing. A fabricated number gets corrected in a week. A blank field gets inherited for a year โ copied into the next report, then the model card, then the investor memo, until nobody remembers the original document never contained an observation at all.
Here is what makes the case genuinely strange. The pipeline I reviewed did the honest thing at the level of the individual cell. It refused to invent a rating. It wrote, explicitly, that any high, medium, or low label assigned there would be a source-less tag that misleads decisions. That is correct behavior, and it is rarer than it should be.
Then it published the frame anyway. It produced the artifact โ the tables, the headers, the star ratings โ and appended a request for data at the end. The refusal was local and correct. The delivery was global and wrong. That is the actual design flaw, and it is not a model flaw. It is an interface flaw. Somebody built an output format before building an output gate.
Write the circuit breaker
Not a warning. Not an N/A with a footnote. A throw.
if (informationPoints.length === 0) throw new Error("EMPTY_PAYLOAD") โ placed before the analysis call, not after it. Fail closed, never open. If your pipeline cannot refuse, your pipeline is not a pipeline. It is a formatting engine with a research department's letterhead.
This matters most in the place I now work. On IronClad Copy, every copyable account requires an audited track record and real-time P&L verification. The verification exists for one reason: to eliminate the blank column. A trader with a missing month is not flat that month. A trader with an empty drawdown field is not risk-free. The blank is the tell, and it is the only tell that never announces itself.
Trust the code, verify the human, ignore the hype. The code that refuses is worth more than the code that renders.
The forward question is not whether your model can produce nine dimensions. Every model can produce nine dimensions now; the format is free, and it will be free forever. The question is whether your pipeline is permitted to return nothing at all โ and who gets held accountable when it doesn't. In the void of 2017, only structure survived. In 2026, structure is the cheapest thing on the market. What is scarce is the discipline to ship an empty page and label it a failure.