The document arrived with nine sections, forty-one tables, and one hundred and sixty-three cells. Every cell read N/A.
It was a due-diligence report. It had been produced by a pipeline I helped specify: ingestion, extraction, then a nine-dimensional framework scoring a protocol on technology, token economics, market position, ecosystem role, regulatory exposure, team and governance, risk, narrative, and supply-chain transmission. The pipeline ran to completion. It emitted a document that looked, at a glance, exactly like analysis.
It contained no facts.
What it contained was a refusal — a long, rigorously formatted refusal to pretend. Stage one had returned an empty information-point list. Stage two, bound by a rule that every conclusion must cite an evidence pointer, had nothing to cite. So it printed N/A in every cell and appended a paragraph explaining why it had stopped.

I have read a great deal of bad crypto research. Most of it fails loudly: a wrong unlock date, an inverted chart, a thread that contradicts itself two posts later. This one failed quietly, and the quietness is the entire story. Because the honest version of that report is rare. The common version is the one where the pipeline, handed an empty input, fills the cells anyway.
The architecture nobody audits
Institutional research desks spent 2025 rebuilding their intake. The pattern is consistent across maybe two dozen shops I have seen or been shown: a scraper layer that pulls article bodies and protocol documentation, an extraction layer that decomposes text into atomic information points, and an analysis layer that maps those points onto a fixed scoring framework. The framework is the visible product. The ingestion layer is the actual infrastructure, and it is the part nobody reviews.

That is a strange allocation of attention, because the framework's correctness is a function of its inputs. A nine-dimensional model fed three true facts and forty-one empty cells does not produce a nine-dimensional conclusion. It produces a nine-dimensional template.
The failure modes upstream are boring and completely predictable:
- Paywalled sources. The extractor receives a 200 response containing a subscription interstitial. Body text length: 41 words.
- Client-rendered pages. The server returns an HTML shell with a and a bundle tag. No prose exists until JavaScript executes. Most crawlers do not execute JavaScript.
- Anti-bot interstitials. A Cloudflare challenge page resolves as valid HTML and passes the length filter.
- Truncated feeds. RSS summaries cut at the first paragraph, which is frequently the hook and never the numbers.
- Canonical redirects. The article URL 302s to a cookie-consent wall. The extractor dutifully summarizes the consent text.
- Readability heuristics picking the wrong node. The article exists, complete, in the DOM. The extractor returns the navigation menu and the "related articles" rail.
None of these throw an exception. All of them return a string. That is the design flaw: the extraction layer communicates success and failure through the same channel — the presence or absence of text — and downstream code is not required to distinguish an empty string from a null.
So the analysis layer receives
[]and has to decide what[]means. There are two available readings. The first: we looked and there was nothing to find. The second: we never actually looked. They are not the same claim, and collapsing them is where research integrity dies.
The empty struct is a signal, not a null
In a typed language,
Noneand""are different values. Most pipelines treat them as the same absence. They are not. One is a measurement of zero. The other is the absence of a measurement.A well-formed information point should carry provenance inline, not in a separate field that a downstream consumer can ignore: