Last month a diligence package landed in my inbox. Nine dimensions. Eleven tables. Technical architecture, token economics, market structure, ecosystem position, regulatory posture, team assessment, a six-row risk matrix, narrative sustainability, supply-chain transmission. Every cell populated. A composite risk rating. A disclaimer citing on-chain data.
The token it described had no contract address. Not an obscure one. None. The upstream decomposition stage โ the parsing layer that extracts title, source, claims, referenced protocols, time sensitivity, source quality โ had returned null across every field. No title. No source. No information points. No domain tag. From that, a downstream model produced three thousand words of internally consistent, professionally formatted, entirely fabricated research.
The report was not wrong. It was well-formed. That is the problem.
The architecture that produced it is standard now, and I have built versions of it. A first stage decomposes raw material into structured fields: what the article claims, who wrote it, which protocols it touches, whether the information is time-sensitive, whether the source is credible. A second stage reasons over those fields and emits an assessment. The separation is sound engineering. It lets you swap the parser without retraining the analyst. It lets you audit the intermediate representation. It is an inheritance hierarchy, and inheritance is a feature until it becomes a trap.
The trap closes when the schema permits a null and the consumer does not model one.
In 2026 the volume problem is real. There are more deployed protocols than there are people qualified to read them. Institutions running ETF vehicles and custody mandates need a paper trail for every allocation. A diligence pipeline that ingests ten thousand documents a week is not a luxury; it is the only way the compliance function scales. I have written standards for this. The M2M custody framework I drafted with three custodial banks was, at its core, the same problem in a different costume: how do you let an automated system act on data it did not personally verify, without letting it act on data that does not exist.
We solved the oracle version of that. We have not solved the document version.
How does an input become empty? I traced four paths this year. A crawler is blocked by a directives file and returns a 403 page that the extractor happily strips to whitespace. A PDF is image-rendered and the text layer comes back as zero characters. A paywalled article returns a preview paragraph and a subscription wall. A JavaScript-rendered page returns the loading spinner's markup. In each case the extraction step succeeds โ it returns a string, just an empty one โ and the retrieval layer that follows does what it was built to do. It searches for relevant chunks, finds none above the similarity threshold, and returns an empty context window. Then the generation prompt runs anyway, because nothing in the pipeline treats an empty context as an exception condition.
For most of the last decade this failure was impossible. A human analyst who received an empty document opened a ticket and asked for the source again. The handoff had a human in it, and humans are, among their other properties, fail-closed. We removed that node for latency reasons and never replaced its function.
Here is the anatomy. A parser returns an object. In most implementations, the fields are strings. An absent title and a title that is the empty string are the same value. An absent source and a source that failed to parse are the same value. The consumer then does what consumers do: it coerces. null becomes "". "" becomes "not specified." "Not specified" becomes an invitation to infer from context. And the model, which is a next-token predictor with an excellent sense of genre, infers.
The vulnerability is not that the model hallucinates. The vulnerability is that absent data and zero data are indistinguishable at the type level.
I have audited this bug before, in Solidity. A mapping returns the default value for any unset key. Zero. If your access-control logic reads balances[msg.sender] and treats zero as "no balance," fine. If your liquidation logic reads a price feed and a missing key returns zero, you have just declared the asset worthless and executed against it. The value did not lie. The type did.
The prompt is where the bug actually lives. A system prompt that instructs the model to produce a nine-dimension assessment is an instruction to produce a nine-dimension assessment. It contains no clause permitting abstention. The model was trained to be helpful and to complete structure, and structure completion is precisely the behavior that turns an empty context window into a confident paragraph about token unlock schedules. I have read generation logs from one of these systems. The retrieved context contains a single token. The output contains forty-one tables' worth of reasoning. Nothing in the architecture flagged the ratio.
In 2017, ahead of the Ethereum Classic DAO recovery fork, I reviewed the community's fix scripts at the contract layer. The gas accounting differed from the reference implementation in a way that only surfaced on contracts with a specific storage layout โ the kind of discrepancy that is invisible in test suites and fatal in production. The scripts assumed a field was populated. It was populated in the test corpus. It was not populated in the wild. We submitted a standardized patch that reverted on absent input rather than proceeding with a default. It cost throughput. It prevented state corruption.
That is the entire argument in miniature. Fail-closed is slower, and fail-closed is correct.
The Compound standardization work in 2020 taught me the same lesson at a different layer. When we drafted the interoperable interest-rate interface, the fights were not about math. They were about what a function does when it receives a parameter it cannot validate. Ninety percent of integration errors in lending forks traced back to two implementations disagreeing about the semantics of an empty return. Once we made absence explicit in the interface, the error rate in downstream integrations dropped by roughly forty percent. Not because the code got smarter. Because the code got stricter about what it would accept.
Terra was the same failure one level up. The on-chain volume anomalies were there. They were visible. They were published, page by page, for months before the peg broke. But a signal with no consumer is not a signal โ it is a record. The equilibrium analysis I published afterward was not novel mathematics. It was a description of a system that had never defined what it would do when its own inputs went to zero, and a market that had never assigned anyone the job of reading the number that said so.
The distinction I keep coming back to is between a control and a convention. A convention says fields should be populated. A control reverts when they are not. Conventions survive until someone is in a hurry. Controls survive until someone removes them, and removing them is a commit you have to defend.
Now the part that makes me unpopular at diligence-vendor demos.
Every pipeline I have been shown this year is benchmarked on three things: coverage, latency, and completeness. How many protocols did it process. How fast. How few cells were left blank. Nobody benchmarks abstention.
An analyst that returns "cannot analyze โ insufficient input" scores zero on completeness. A pipeline that fabricates nine dimensions of plausible structure scores one hundred percent. The market is not selecting for accuracy. It is selecting for the absence of visible gaps, because a visible gap is what a compliance officer has to explain to an examiner.
So the incentive gradient points one direction. Fail-open systems get funded. Fail-closed systems get replaced. The human analyst in the original chain โ the one who refused to fill the template and returned a diagnostic instead โ did the correct thing, and by every commercial metric available, that was a pipeline failure. Nobody sends a thank-you note for an abstention.
I have watched a vendor demo where the presenter was asked what happens on a failed parse. The answer was that the system "degrades gracefully." In practice that means it fills the gap with priors โ sector averages, typical unlock schedules, common governance structures. The output is not random. It is a statistical summary of the industry, wearing the specific project's name. Which is, from a risk-modeling standpoint, worse than random. Random is loud. A plausible substitute is quiet.
Execution is final; intention is merely metadata. The report executed. It has a timestamp, a hash, and a place in the diligence file. Whether the model "intended" to fabricate is irrelevant. The artifact exists and it will be read by someone who was not in the room.
This is where the AI-agent custody standard becomes a live risk rather than a theoretical one. An autonomous agent with a delegated mandate reads an oracle, sizes a position, and settles. If the oracle returns null and the agent's type system renders null as zero, the agent does not malfunction. It executes flawlessly on a fact that does not exist. The absence of a price becomes a price of zero, and zero is a number you can act on. Every M2M framework I have reviewed this year is one unvalidated null away from that outcome.
The research pipeline is that same agent, wearing a suit.
My forecast for the next eighteen months is not another reentrancy exploit. Those get caught now; the tooling is good and the bounty market is efficient. The next institutional-scale loss will arrive as a diligence artifact. A report with the right shape, the right headers, the right disclaimer, generated from an input that was never there, cited in an allocation memo, and discovered only when the position has to be marked down.
The fix is not a better model. Better models fabricate more convincingly. The fix is a schema that makes absence unrepresentable as presence โ optional types at the boundary, mandatory revert on unset required fields, abstention treated as a first-class output rather than an error code. Sign the intermediate representation. Publish the abstention rate alongside the coverage rate.
And ask your vendors one question before you sign: when the input is empty, what does your system return?
If the answer is a document, you do not have a diligence process. You have a latency generator.