CompanyGraph is not presented as perfect. It is a system that has learned to distrust itself in specific, inspectable ways.
Real cases where a claim outran its evidence — where each entered the system, what changed, the guard now in place, and what remains limited.
Every claim CompanyGraph shows a reader travels a path — data, quality, claim, proof, evidence, trust, placement, surface — with feedback steering the earlier stages. This page is the steering stage made public: real defects, found by the system's own checks or by deliberate audit, each traced to the stage where the mistake entered, with what changed because of it.
Newspapers publish corrections because a record of fixed mistakes is stronger evidence of care than a claim of accuracy. Same idea here. These cases are dated, specific, and written the same way each time:
- What went wrong — the claim a reader could have met, stated plainly.
- Where it entered — the stage of the path that let it through, which is not always where it was noticed.
- What changed — the actual fix.
- The guard now — what catches the class of mistake, not just the instance.
- What remains limited — because "fixed forever" is exactly the kind of claim this product refuses.
This list is representative, not complete. It grows as corrections happen. The current trust state of every observation — what these checks have and have not confirmed today — is the companion page, How far to trust each observation.
A ratio with no ceiling
What went wrong. A structural reading — "priced high relative to the business" — fired whenever price-to-sales exceeded a threshold, with no upper bound and no validation of the provider-computed ratio underneath. Broken inputs sailed through: companies with collapsed revenue figures showed price-to-sales values in the tens of thousands, and the system dressed those artifacts as a structural observation. Hundreds of companies were affected.
Where it entered. The quality stage. A corrupt input crossed into the claim layer with no guard — while sibling readings already had exactly the needed small-denominator guards. The failure class was known; this instance was simply never given the same protection.
What changed. A plausibility band now bounds the reading (June 2026), mirroring the sibling guards, and implausible provider ratios are gated at the source before anything is computed from them.
The guard now. Ratio plausibility checks at the data boundary, and a rule learned the hard way: a guard that protects one metric but not its siblings is a hole, not a policy.
What remains limited. Provider-computed ratios are still imperfect upstream. A plausibility band bounds what we will say; it does not verify the ratio.
Money compared in the wrong currency
What went wrong. Cross-company money comparisons — market capitalization, revenue, scale bands — were made in each company's native reporting currency. A company reporting in yen can show a number twenty times larger than one reporting in dollars while being a fraction of its size. One comparison surface shipped with this bug live; an audit then found several more places sharing the same root.
Where it entered. The quality stage again — units and currency are part of a number's meaning, and a comparison that ignores them is arithmetic on words. The bug hides on US-only data and surfaces the moment a foreign company enters, which is why it survived review.
What changed. Every cross-company money comparison now uses USD-normalized values (June 2026); native-currency values are for single-company display only, with their currency symbol. The doctrine is written down, and the known violations were fixed together as a class.
The guard now. Dedicated USD-normalized fields for comparison, and a standing test habit: never validate a comparison surface on US-only companies.
What remains limited. Native values are still shown in single-company contexts by design, so every new comparison surface must choose the normalized field. That choice is held by doctrine and review, not by a compiler — which means it can be gotten wrong again, and this page will say so if it is.
A name that said more than the formula
What went wrong. An observation named as a margin trend actually measured operating income rising — the formula never touched margins at all. Five interpretations consumed it under the false meaning. Every consumer downstream — matching, evidence, trust records, captions — reads the name, never the math, so a misnamed measurement is a false claim wearing a valid proof.
Where it entered. The claim stage, at naming time, years before it was caught. The doctrine — a name states what the formula measures, never more — existed; the older catalog predated its enforcement.
What changed. Reader-facing titles were corrected first; then ten misleading machine keys were renamed in place across every record that carried them (July 2026), so the stored keys stopped lying too. The rule that shipped with the fix: a key may be ugly, but it must not lie.
The guard now. Behavioral witness tests block a new observation from entering the catalog without declaring what it measures, and naming is treated as part of the formula's contract — reviewed like code, because it functions like code.
What remains limited. Renaming corrects the label, not the history of anyone who read the old one. And name review is a human judgment; the guard catches structure, not every shade of implication.
The square root that failed quietly
What went wrong. A hand-rolled square-root routine inside one observation's formula silently failed to converge on large inputs, inflating the result roughly 4.75× and producing confident false firings.
Where it entered. The claim stage — an implementation detail no review had caught, because the output looked plausible.
What changed. This one the system caught itself, exactly as designed: the independent proof stage recomputes observations through a different code path, and its recompute disagreed with the engine 215 times. The contradiction count named the bug; the routine was replaced with the standard library implementation and re-run (30 June 2026), and the contradictions went to zero. The observation's trust level then moved up — calibration goes both directions when the check earns it.
The guard now. The proof stage itself: a claim-maker is never allowed to certify its own claim. The recompute path shares no code with the engine, precisely so one bug cannot hide in both.
What remains limited. Even now, this observation does not appear in reports — its traditional name is a valuation verdict that the recompute does not support. Being computed correctly and being worth stating are different questions, answered by different parts of the system.
One truth living in two places
What went wrong. During a long migration, one set of financial figures lived in two places at once — the owning service and a "temporary" synchronized copy. The owning side fixed a currency-unit bug; the copy kept the corrupt values. At audit (July 2026), a large share of companies differed materially between the two — the same company could exist at two different market capitalizations depending on which copy a surface read. One downstream consumer even declined obviously absurd figures on its own — which is luck, not a guard: a plausible wrong number would have sailed through.
Where it entered. The ownership boundary. Duplicated truth has no contract: no compile error, no test, nothing that makes a fix travel from the original to the copy.
What changed. Sanity gates now bound the values, and cross-company benchmarks are mirrored from the owning source rather than recomputed from the copy.
The guard now. A named rule — no data lives in two places; any temporary duplication must carry a named cleanup phase — and deterministic plausibility bands where the duplicate still exists.
What remains limited. Honestly: the duplicate itself still exists. Collapsing it is a named, open piece of work, and until it lands this page lists it as the system's known weakest point. That is what this page is for.
True numbers, presented as current
What went wrong. Roughly 40% of covered companies had financial statements around eighteen months old — and company pages rendered their figures with no "as of" line and no staleness warning. Every number was genuinely reported; presenting them undated silently asserted they were current. An old true number shown as current is a false claim.
Where it entered. The surface stage. The dates existed in the data all along; they simply were not part of the rendered claim. Freshness tooling existed but was internal-only.
What changed. Company pages now carry a deterministic as-of line — the newest fiscal period on file — and a visible flag when the newest annual statement is eighteen months old or more (July 2026).
The guard now. "As of when" is treated as part of every claim, not metadata. Reports carried their as-of dates already; now the free pages hold the same rule.
What remains limited. The underlying statements are annual, and coverage depends on an upstream data provider. A staleness flag makes age visible; it cannot make data young.
Our words in the company's mouth
What went wrong. Generated reports attributed CompanyGraph's own model-written structural readings to the company itself — phrasing like "the company describes…" in front of text the company never said. On well-known companies the error was invisible, because the model's account tends to match reality. On a lesser-known company, the model invented a specific capability — and the system presented that invention as the company's own account of itself. A fabricated claim, wearing a real company's voice, on an indexable page.
Where it entered. The surface stage — the report writer's attribution default. The deeper cause: a claim's origin was not carried with the claim, so nothing downstream could check attribution against source. The rule against this existed in doctrine; no mechanism enforced it.
What changed. The attribution boundary is now explicit (July 2026): generated structural readings are attributed to CompanyGraph — "CompanyGraph reads this as…" — and "the company's own statements" is reserved for the company's reported figures. Previously generated reports were regenerated under the rule.
The guard now. Origin is part of the claim. Model-generated interpretation is labelled as interpretation wherever it appears, and the writer's instructions carry this case as the standing counterexample.
What remains limited. Generated interpretation is still generated. The fix makes its source honest; it does not make the reading infallible — which is why every reading also carries its support level.
The recurring shape
Seven cases, one anatomy: a claim outran its evidence at a boundary that carried no guard. The ratio had no ceiling, the currency was not part of the number, the name outran the formula, the arithmetic certified itself, the copy had no contract, the date was not part of the claim, the origin was not attached.
And one meta-lesson sits on top, found by auditing the audits themselves: several of these rules were doctrine without mechanism — true in the documentation, unenforced in the pipeline. A rule that lives only in prose fails exactly when nobody is looking. The corrections above each ended the same way: the rule was moved from prose into a gate, a test, a band, a boundary.
None of this makes the current system correct. It makes it corrected — so far, in these specific ways, with the checks now standing. The live state of what those checks currently confirm is the trust ledger; the path every claim travels, including the steering stage that produced this page, is From data to checked claims.