← All guides

When the documentation is wrong, and the engine says so

Every compatibility table on the internet is built by reading documentation. This one is built by running formulas, and the difference shows up in an uncomfortable place: when an engine disagrees with its vendor’s own page, it is sometimes the page that is wrong.

Our corpus asserts a documented figure only after re-deriving it independently — in exact rational arithmetic or at 50 digits, from the formula the vendor’s own page states, using a clean-room implementation of the day-count and distribution procedures written for this project and used by no engine. That discipline exists to catch our own mistakes. It also catches theirs. Across 586 executed functions we have recorded 29 places where a vendor’s published page is contradicted by its own inputs, by its own table, or by the live engine: 23 on Microsoft’s pages, 5 on Google’s, 1 on The Document Foundation’s.

This is not a scoreboard, and it is not a complaint. Function documentation is genuinely difficult: the pages are old, the examples are hand-computed, the data tables get re-rolled and the prose does not always follow. Most of the 29 are the kind of slip anyone would make. The reason to publish them is narrower and more useful: if you are checking your own migration against a vendor page, these are the specific pages that will mislead you, and each one has a citation and a returned value beside it.

The surprise

Three of the 29 were caught by an engine, not by us. Our corpus originally asserted Microsoft’s printed 1.812462 for one of the two figures in the T.INV.2T Remark; all four LibreOffice builds returned 1.812461, which sent us back to the derivation, which agreed with the engine. Google’s ISDATE page publishes TRUE for an input on which its own live engine returns FALSE. And LibreOffice’s RAWSUBTRACT help page prints a figure that LibreOffice’s own engine contradicts in the third significant digit. When the documentation and the engine disagree, an executed corpus is the only thing that can tell you which one to trust.

How a page earns a place on this list

The bar is deliberately high, because “the documentation is wrong” is an easy and lazy thing to say. A page is counted here only when it makes a factual claim that is not true on its own terms — a published result that its own inputs cannot produce, a remark that contradicts a table on the same page, a value the live engine refutes. Three large categories are deliberately not counted:

Microsoft: 23

The Excel column is Microsoft’s documented behaviour as recorded in our corpus. We do not run Excel, so nothing here is a measurement of Excel — the claim being made is only that a published figure does not follow from the published inputs, and the derivation is what supports it. Where the two engines we do run agree with the derivation, that is corroboration and it is noted.

PageWhat it publishesWhat is trueGoogle Sheets (executed)LibreOffice Calc 25.8.7.3 (executed)
SUMX2MY2=SUMX2MY2(A2:A8,B2:B8) = -55Over the page’s own table, data starts in row 3; the printed range takes in the header row and only six of seven pairs, and gives -64. The two sibling pages publish A3:A9 over a byte-identical table-64 (verbatim range), -55 (corrected)-64 (verbatim), -55 (corrected)
T.INV.2T and TINVA shared Remark citing 2.28139 and 1.812462Both figures are wrong. 2.28139 is a digit transposition of 2.228139; 1.812462 is a last-digit error for 1.8124612.228138852 and 1.8124612.228138852 and 1.812461
DISC0.001038 for settlement 2018-07-01, maturity 2048-01-01Those inputs give 0.000686384169. The printed figure is reproducible only with a 2038 maturity — a stale value left behind when the dates were rolled forward0.0006863450650.000686384169
SEC“the secant of a 45 degree angle”, result 1.903591.90359 is 1/cos(45 radians). 45 degrees would give 1.4142135624. The Remarks bullet, which tells you to convert degrees with PI()/180, is the correct half of the page1.903591.90359
SECH“the hyperbolic secant of a 45 degree angle”The same unit error on the sibling page; the published figure is the radian onesee note below5.72504E-20
TBILLEQProse: DSM is “computed according to the 360 days per year basis”. Result: 0.09415A 30/360 count from 2008-03-31 to 2008-06-01 is 61 days and gives 0.09413. Only the actual count, 62 days, reproduces the page’s own 0.09415, so the figure is right and the sentence is wrong0.094150.09415
TDISTRemarks: x < 0 returns #NUM!Two bullets later the same page publishes the identities TDIST(-x,df,1) = 1 - TDIST(x,df,1) and TDIST(-x,df,2) = TDIST(x,df,2), defining the function at negative x in the same breath as forbidding it#NUM!#VALUE!
ISPMTArgument table: per “must be between 1 and Nper”The Remarks on the same page say “ISPMT counts each period beginning with zero, not with one”. The two indexing rules are incompatible-64814.8148-64814.8148
MAXA“Arguments that contain text or FALSE evaluate as 0”One line later: “Empty cells and text values in the array or reference are ignored”. For a text cell inside a range the two give opposite answers00
MINAthe identical contradictory pairsame00
VARPAthe same contradiction, third pageResolved the way AVERAGEA’s worked example resolves it — text counts as zero1.251.25
DPRODUCT, DSTDEV, DSTDEVPdatabase range A5:E11Over the shared example table that range starts one row below the header, leaving the field label “Yield” unresolvable — it cannot produce any published result. The sibling pages DCOUNTA, DVAR and DVARP cite A4:E10, which works800, 2.96648, 2.6532998800, 2.96648, 2.6532998
BESSELJ0.329925829The true value is 0.32992572769… The published figure is wrong in the 7th decimal — a discrepancy about 100× larger than any rounding residue#NAME? (Sheets has no BESSELJ)0.329926
BESSELI0.981666428A truncation of 0.98166642857…, which rounds to 0.981666429 at nine places#NAME?0.98166643
BESSELK0.277387804The true value is 0.27738780045…, so the correct nine-place figure is 0.277387800#NAME?0.2773878
CHISQ.INV3.283020286A truncation of 3.283020286759…, which rounds to 3.2830202873.283020293.28302029
DBCS‘=DBCS("EXCEL") equals "EXCEL"’The argument comes back unchanged, which is impossible under the page’s own stated conversion rule. The line is identical to one on the page for the inverse function, ASC#NAME?#NAME?
JISthe same unchanged-argument exampleExample 2 on the same page is entirely images, so nothing is quotable from it either. Our corpus derives the value instead, and LibreOffice’s JIS confirms it#NAME?EXCEL
GAUSSa Result cell containing the literal text “=GAUSS(2)”The example table was published unevaluated; the only usable figure is in the Description prose0.47724986810.477249868052
AMORLINC=AMORLINC(A2,A3,A4,A5,A6,A7,A7)The published formula passes A7 (the rate, 0.15) where the basis argument belongs; A8 (1) is the basis in the page’s own data table. Harmless here, because 0.15 truncates to basis 0 and period 1 is unprorated360360
ODDLPRICE and ODDLYIELDprose: the arguments come from “cells A2:A10”The formula printed on the same page takes eight arguments from A2:A9. An off-by-one in the prose, not in the figure — both published results reproduce exactly#NAME? (Sheets has neither)99.88 and 0.04519
FORECAST.ETS.STATstatistic type 6 described as “the symmetric mean absolute percentage error metric”That is the definition of SMAPE, which is type 5. The type-6 text is a copy of the type-5 text; type 6 is MAE#NAME?TRUE (the structural MAE ≤ RMSE assertion holds)
TRIMRANGEan equivalence table whose third row says Z10 in the operator column and E10 in its own TRIMRANGE equivalentOne of the two ranges is a slip; the rows are meant to be equivalent#NAME?#NAME?

Two notes on reading that table honestly. The SECH row’s Google Sheets value sits at a magnitude where our numeric comparison tolerance cannot separate two answers, so we do not cite it as agreement in either direction. And TDIST’s LibreOffice cell is #VALUE! where #NUM! is documented — that is a separate, unrelated finding about error codes, not part of the documentation defect.

Google: 5

PageWhat it publishesWhat is trueGoogle Sheets (executed 2026-09-01)LibreOffice Calc 25.8.7.3 (executed)
ISDATE=ISDATE("1969-20-07") → TRUEThat is only consistent with a year-day-month reading, and the page says nothing about locale. The live engine returns FALSE. Our test file predicted this outcome in writing before the run: if the engine returns FALSE, the page is the thing that is wrongFALSE#NAME?
EPOCHTODATEa conversion recipe in the Notes that adds 25,568The page’s own example table maps timestamp 0 to 1/1/1970, whose serial in Sheets’ 1899-12-30 system is 25,569. The constant in the Notes is one day short. Re-fetched to rule out a transcription error on our side25569#NAME?
DIVIDENotes: “DIVIDE is equivalent to QUOTIENT.”The same page’s headline defines DIVIDE as the / operator, and its own gloss of QUOTIENT says “without the remainder”. 7/2 is 3.5 and QUOTIENT(7,2) is 3, so the difference is 0.5, not 00.5#NAME?
AVERAGE.WEIGHTED=AVERAGE.WEIGHTED(A1:A2, B1:B2, C1, C2) → 6.2In that same table column C is the Formula column: C1 holds the header word “Formula” and C2 holds another formula. The row must have meant A3 and B3, which reproduce 6.2 exactly6.2 (on the corrected references)#NAME?
TO_PURE_NUMBER“If value is not a number… TO_PERCENT returns value without modification.”The rule paragraph on TO_PURE_NUMBER’s own page names a different function as its subject. TO_PERCENT has its own page carrying the same sentence correctly. Re-fetched the same day to rule out a transcription errorabc#NAME?

The Document Foundation: 1

PageWhat it publishesWhat is trueGoogle Sheets (executed 2026-09-01)LibreOffice Calc 25.8.7.3 (executed)
RAWSUBTRACT“=RAWSUBTRACT(0.987654321098765, 0.9876543210987) returns 6.53921361504217E-14”The exact IEEE-754 difference of those two literals is 6.50590692430341…E-14. RAWSUBTRACT is defined as the raw double difference, so nothing is left for an implementation to choose — and the figure differs in the third significant digit#NAME? (Sheets has no RAWSUBTRACT)6.5059069243 (×1E14) on all four builds — LibreOffice’s engine contradicts LibreOffice’s help

That page is the only numeric example the function has, which is what makes it worth naming: there is nothing else on it to check yourself against.

One we deliberately did not count

LibreOffice’s CEILING help documents the mode-omitted case as rounding toward zero and prints the worked example CEILING(-45.67;-2;0) = -44. All four builds actually return -46 for =CEILING(-45.67,-2), matching Microsoft’s documented behaviour and Google Sheets (executed 2026-07-29 and 2026-08-29 respectively). By the test used on this page — a page contradicted by its own engine — that would qualify. We classify it instead as a cross-engine default-behaviour question, because the mode argument is exactly the thing the two vendors define differently and the help is describing a documented mode rather than misprinting a figure. It is a judgement call, and we would rather show it than absorb it.

Why executed verdicts beat documentation

None of the 29 is dramatic on its own. Taken together they make a narrow point that matters for anyone doing a migration by reading:

A published figure is a claim, not a measurement. Worked examples are computed once, by a person, and then live on a page for fifteen years while the data table around them is edited. DISC’s stale 0.001038 and SUMX2MY2’s off-by-one range are both that story. If you check your migration by comparing your output to a documented example, you are comparing two things that were never guaranteed to agree.

Pages contradict themselves more often than they contradict reality. Nine of the 23 Microsoft entries are internal contradictions — a Remark against a table, a description against a result, one page against its own siblings — rather than wrong numbers. That is the failure mode documentation is most prone to, and it is invisible unless you try to satisfy both halves at once, which is what writing a test case forces you to do.

An engine is a second opinion you can actually query. The three findings in the box at the top of this page exist because a running engine disagreed with a page and something had to give. That only works if you execute; a table built from documentation would have copied the wrong number straight through, and would have looked authoritative doing it.

The derivation is the real product. Where our corpus asserts a value we re-derive it first, and every note records how — which formula, which day-count procedure, which arithmetic, which sentence on which page, and the date the page was read. That is what makes it possible to say “this figure is wrong” without simply meaning “an engine disagreed with it”. When the engines disagree with each other, the derivation is the tiebreak.

Honest limits

The count of 29 is a classification, and classifications have edges. We have applied the test described above — a factual claim untrue on its own terms — and shown the largest borderline case we excluded. Someone applying a looser test would count more; someone requiring a wrong number rather than a wrong sentence would count around a dozen. Every entry is named, so the count can be disagreed with in the open.

The Excel column throughout is Microsoft’s documented behaviour as recorded in our corpus. We do not run Excel. This is the important caveat on this page and it cuts both ways: we cannot show that Excel returns something other than a published figure, only that the figure does not follow from the published inputs under an independent derivation. Where Excel’s own behaviour is the question — as it would be for TDIST at negative x — we have no measurement and say so.

The Google Sheets column is executed output from dated runs, because Sheets has no version number to pin: a formula-only .xlsx carrying no cached results goes to Google Drive, is recalculated by Google’s engine, and comes back as .xlsx for readback, with a deterministic =1111+2222 canary in every sheet proving the recalculation happened. The Microsoft-page rows ran on 2026-08-31, the Google-page rows and RAWSUBTRACT on 2026-09-01, and CEILING on 2026-08-29. Sheets’ export rounds floats to ten significant digits, which is why some values above carry fewer digits than their LibreOffice counterparts.

The LibreOffice column is executed output from Calc 25.8.7.3, and every case cited here returned identical results on 24.2.0.3, 24.8.7.2 and 25.2.0.3. Those four builds are the only ones we tested.

Vendor pages change, and several of these may be corrected after this was written. Every note in the corpus records the URL and the date the page was read — most of them 2026-08-31 — so an entry that no longer matches the live page is a fixed defect rather than a wrong claim, and we would rather hear about it than not. See our methodology for how recalculation is proven rather than assumed, and the function pages for SUMX2MY2, T.INV.2T, ISDATE and RAWSUBTRACT for the per-engine support matrices.

Check before you migrate