Research note · Verification

Wrong-object errors in research pipelines

A computation can execute exactly as specified on the wrong object, such as the wrong document, security or probability. Such defects raise no error, pass every test written for the computation, and return well-formed, plausible output. Our defect register recorded seven over eighteen days; in the case examined here, the only check comparing across the two questions at issue was scoped on the field the defect had corrupted, so it never ran.

Two probabilities on one artifact, and every comparison that was made The comparison that would have caught it existed, and was scoped on the field the defect had corrupted QUESTION 1 — DOES THE TRANSACTION COMPLETE? point estimate low nineties its own lower bound low nineties the number sized on low nineties COMPARED passes, correctly COMPARED two copies of one number the only comparison that crosses questions scoped on the artifact’s type label — skipped whole QUESTION 2 — DOES A BID ARRIVE AT ALL? published band low-to-mid teens THE GAP ON ONE ARTIFACT 84.55 percentage points between the probability published and the one estimating completion WHAT THE CHECKER REPORTED on the defective artifact 55 violations on its repair 55 violations every comparison the file made stayed inside one question
The two checks that ran compared a completion estimate with its own lower bound and a gate’s copy of the sizing number with the sizer’s copy, and both passed correctly. The comparison that would have caught the defect was conditioned on a field the defect had set wrongly.

Structure of the defect

A pipeline computation selects an object, computes on it, and satisfies a contract describing the output, and verification concentrates almost entirely on the computation. A unit test fixes an input the author chose, so it says nothing about the selection the running system performs. Type and range checks pass because a wrongly selected object is usually of the right type and in range, and the output contract holds because a correct computation on a wrong input produces a well-formed answer.

In every recorded instance the code did what it was written to do, and the number was of the right magnitude and units. Because the answers resemble what the reader expects, the failure survives review by a person as readily as review by a test.

Software testing calls the general obstacle the oracle problem, surveyed by Barr and colleagues in 2015: many systems have no automatic means of telling that an output is correct, so testing reduces to confirming what the programmer already believed. Metamorphic testing, proposed by Chen, Cheung and Yiu in 1998, is the standard response and asserts relations between outputs rather than checking any output against a known truth. The class described here is the oracle problem as quantitative pipelines produce it, and the useful assertions likewise relate independent parts of a system.

Seven recorded instances

Seven entries were recorded between the twelfth and the twenty-ninth of one month. They are described by mechanism rather than by episode.

Two probabilities on one artifact

One artifact published two probabilities, one for whether a transaction completes and one for whether a bid arrives at all. The position was sized from the first while the headline carried the second, 84.55 percentage points apart, and nothing on the artifact declared which question the position took. Run against the archived defective artifact and against its repair, the coherence checker returned the identical 55 violations on both. Its source already contained the comparison that would have caught the defect.

Three probability comparisons, all working as written

CheckWhat it comparedOutcome
Point against its own floorA completion point estimate against its own lower bound — both the same estimatePassed, and correctly
Gate copy against sizer copyTwo renderings of the one number the sizer usedPassed, and correctly
Band against pointThe only cross-question comparison in the file, at a tolerance the observed gap of 0.845 exceeds by a wide marginNever evaluated

The third check is conditioned on the artifact’s type label. The defective artifact carried the other label, so the block was skipped whole rather than failed.

Every other pairing stayed within one question, and the single comparison across the two probability families was conditioned on the artifact’s type label, which is the field this defect corrupts, since the wrong label is what puts a bid-arrival probability on an artifact whose governing document says the bid already arrived.

An invariant scoped on a field the defect corrupts cannot see the corruption.

The structures holding the mismatched probabilities were also on the checker’s skip lists for prose scanning, and three further fields carrying the same numbers were read by no check.

Three rules

  1. An invariant must not be scoped on a field the defect it hunts can corrupt. It should be scoped on evidence independent of the thing checked, such as the governing document rather than a type label, and should fail closed, treating a missing declaration as a failed one.
  2. Comparing a value against another copy of itself is not a check, since agreement between two renderings of one number shows only that the renderer works. Informative checks compare across families and questions, as metamorphic testing relates outputs to one another.
  3. A check that cannot fail is not a check. Every invariant should ship with a failing control built from the real defect and be re-run against it on a schedule, demanding a failure on the archived defect and a pass on the archived repair, rather than relying on the existence of the code. The scheduled test should itself report failure when the invariant is deleted, weakened to report everything clean, re-scoped on the corrupted field, or deprived of its inputs.
An invariant that would have passed on the defect it was written for is worse than none, because it converts an open hole into a documented guarantee.

Recurrence on new axes

After the repair the class recurred on three axes that no existing check read.

An expected completion horizon was taken from a default for that class of transaction rather than from the document stating the expected timing. Because downstream rates are annualised, the substitution rescaled each rate by the ratio of the two horizons, a median of 2.25 times across twenty-one items and up to 19.3 times. Timing checks that compared an artifact’s clock with itself passed, since every figure came from the same default; a horizon can be wrong only relative to a document.

An analysis was correct up to a conversion date and silent after it, when the holder stops owning the analysed security and begins owning a different one. Every existing check passed because each described a position that ceases to exist at that boundary.

The resource guard above was committed inside the module whose documentation records an earlier instance of the same class on the same subsystem. A module can document a defect class and commit it on a different axis, which is why rules generalise where a list of past fixes does not.

Limitations

Further reading

How we verify what we publish

Our validation policy, the checks that govern it, and a plain-language record of the ideas that did not survive.

Research Integrity More Research