the record · errata
The Record · errata

Everything we got wrong.

Every register here makes claims about somebody else's system. The only thing that makes that defensible is a permanent, specific account of the times we were wrong — kept with the same care as the findings, and never quietly edited away.

Errata
8
append-only; nothing is deleted
Reached the public
4
published, then withdrawn
Caught first
4
disclosed anyway, but not the same thing
Found by machinery
4
2 by a control or fault injection, 2 by a written test

Why this page is specificA retraction is the cheapest thing to fake and the hardest thing to fake precisely. Every entry below names the exact wrong value, the exact mechanism, and the test that now makes it unconstructable. That is checkable. “We take accuracy seriously” is not.

Two kinds, never blurred. Errors that reached the public are marked separately from errors caught before anyone saw them. We are not owed credit for the ones that never got out.

§ 0.2 — The record of corrections

Entries, oldest first

E-001

PUBLISHED, THEN WITHDRAWN 2026-08-04 found by our own machinery
Claimed
93 FXRP redemptions were proven defaults — agents that took a fee and never delivered XRP.
Actually
Zero of them were defaults. All 91 agents examined had paid, in full, on time.
Mechanism
The FDC request asked whether a payment of valueUBA existed. An agent owes valueUBA − feeUBA. The amount we asked about had never existed, so the oracle truthfully attested its absence for every redemption. The attestation was correct; the question was wrong.
Caught by
A control test that required the verifier to REFUSE redemptions the chain already recorded as performed. It refused none of them, which meant the request could not distinguish paid from unpaid.
Now prevented by
amountOwed() is now the single place the obligation is computed, verified against settled redemption 43128188 whose real XRPL payment delivered exactly valueUBA − feeUBA.

E-002

PUBLISHED, THEN WITHDRAWN 2026-08-04 found by re-reading the evidence
Claimed
Control C3 reported a 400 UBA exception against Flare, asserting availableFunds + escrowedFunds ≤ totalAvailableUBA.
Actually
Those figures were never defined to relate. The 400 UBA is a fee the asset manager nets off.
Mechanism
Two numbers from two contracts were compared because they looked comparable. Nothing in the protocol says they should be equal, so the difference was not a finding.
Caught by
Reading the asset manager's own accounting after the exception was published.
Now prevented by
The wedge is now disclosed as an observation (C5) rather than judged, and the regression is pinned by a test asserting the exact 400 UBA gap is expected.

E-003

PUBLISHED, THEN WITHDRAWN 2026-08-04 found by our own machinery
Claimed
Control C3 asserted escrowedFunds = totalAvailable − immediatelyAvailable, and reported CLEAN every period.
Actually
The control could not fail. It had been printing CLEAN for reasons unrelated to the vault's health.
Mechanism
coreVaultAvailableAmount() derives both of its outputs from the same escrowedFunds storage slot. Corrupting that slot from 500,000,000,000 to 999,999,999,999 moved both sides of the identity together and the control stayed green — a tautology wearing the costume of a reconciliation.
Caught by
Deliberate fault injection on a forked chain. Nothing else would have surfaced it.
Now prevented by
C3 now reconciles Flare's escrowedFunds against XRPL Escrow objects — two chains that cannot move each other — and the red run fails the build if C3 survives its own fault.

E-004

CAUGHT BEFORE PUBLICATION 2026-08-04 found by re-reading the evidence
Claimed
A draft of C3 asserted availableFunds + escrowedFunds ≤ account balance, producing a 497,844,875,522 drop shortfall against Flare.
Actually
There was no shortfall. The arithmetic double-counted every escrow.
Mechanism
XRPL escrow REMOVES XRP from account_data.Balance and holds it in Escrow ledger objects. Adding Flare's escrowed figure to a balance that already excludes it counts the same XRP twice.
Caught by
Checking the live XRPL account objects before publishing the exception.
Now prevented by
A regression test asserts the exact bad arithmetic still produces 497,844,875,522 and that the current control reports CLEAN on the same data.

E-005

CAUGHT BEFORE PUBLICATION 2026-08-05 found by re-reading the evidence
Claimed
The status badge reported a verdict as fresh.
Actually
The badge could never go stale. Its computed age was −21 hours, because freshness was derived from the day under test rather than when the report ran.
Mechanism
CV-1 recorded a period, not a timestamp. Anchoring the period to end-of-day dated every report into the future, and a negative age passed the freshness budget trivially.
Caught by
Reading the emitted JSON instead of trusting that the badge rendered.
Now prevented by
CV-1 records generatedAt, and a future-dated report renders UNKNOWN rather than vouching indefinitely.

E-006

CAUGHT BEFORE PUBLICATION 2026-08-05 found by a test written for it
Claimed
The red run forked Coston2 and reconciled it against the Coston2 XRPL testnet vault.
Actually
It would have reconciled a Coston2 fork against the REAL XRP Ledger — two unrelated systems, compared with complete confidence. The controls would have 'fired' and proven nothing.
Mechanism
xrpl.ts chose its XRPL cluster at module load. ESM hoists imports above the importing module's statements, so the red run setting NETWORK at the top of its own file ran too late.
Caught by
Grading the subjects, which forced the question of what evidence V3 actually rests on. The hoisting behaviour was then reproduced in a five-line test rather than assumed.
Now prevented by
Endpoints resolve per call, so the caller's network selection is honoured.

E-007

CAUGHT BEFORE PUBLICATION 2026-08-05 found by a test written for it
Claimed
Evidence packs were anchored to a Flare block, an XRPL ledger and a cross-chain skew of 0 seconds.
Actually
None of the three anchors described the state in the pack. The block was read AFTER the contract reads, so it named a later height. The XRPL ledger was the newest of the last 200 transactions, not the ledger the balance and escrows were read at. The skew was hardcoded, never measured.
Mechanism
Each anchor was taken from whatever value was conveniently to hand rather than from the read itself. A replayer at the stated Flare block could legitimately compute a different opinion, and the stated XRPL ledger was simply unrelated to the balances beside it.
Caught by
Writing a regression test that asserted the anchor equals the height the state was read at. The first version of that test failed twice, and the second failure exposed a deeper form of the same bug: the recorded XRPL evidence did not carry its own ledger, so a replayer could not confirm the anchor from the pack at all.
Now prevented by
Reads are pinned to a block number obtained first; accountLedgerState returns the ledger and close time it used; skew is computed from them and reports -1 when it cannot be established. The pack is self-describing, and tests assert the anchor matches the recorded evidence.

E-008

PUBLISHED, THEN WITHDRAWN 2026-08-05 found by re-reading the evidence
Claimed
223 TEE machines are registered, of which 95% carry one shared code hash — published under a freshness badge reporting the scan as current.
Actually
The registry held 250 machines. The published figure was 12% wrong and had been for roughly twenty-nine hours, on the headline number of an entire register.
Mechanism
The badge measures the AGE of a scan, and age was silently doing duty for correctness. Nothing ever compared the committed snapshot against the chain, so a scan could be hours old and already wrong while reporting itself fresh. The ratios the register actually concludes from were barely affected, which is what made it survive: the page looked right.
Caught by
Re-reading the live registry during an audit and comparing it by hand to the number on the page. No control caught this, and the tests were complicit rather than silent — they asserted the count equalled 223 while reading the same stale file the page did, so the whole suite agreed with the error. A test that reads the artefact under test cannot detect that the artefact is stale.
Now prevented by
checkDrift() reads the live registry total and classifies the gap CURRENT, IMMATERIAL, MATERIAL or UNKNOWN against a 2% materiality threshold; driftIsPublishable() blocks the publish on MATERIAL, and on UNKNOWN, because failing to check is not evidence nothing moved. A regression test pins 223-against-250 as MATERIAL. It is exposed as `pnpm --filter @therecord/reprod drift`, so the check is a command a stranger can run against us rather than a promise we make about ourselves.

The patternThree of these are the same error wearing different clothes: a comparison between two numbers that were never defined to be equal, or that could never disagree. That is the failure mode of assurance work, and it is invisible from the inside — every one of them produced confident, well-formatted output that happened to be meaningless.

Only a deliberate fault distinguishes a control that holds from one that cannot fail. That is why the red run exists, why it runs in CI, and why V3 on the verifiability scale requires it.