=FormulaProof
1

FormulaProof · Evidence

Execution log

What Google Sheets regex actually supports, and what it silently does instead

Ran
Engine
Google Sheets (live, via Sheets API v4)
Locale
en_US
Host
Windows_NT 10.0.26200 · Node v24.15.0
Result
21 of 21 as expected
Cell Formula What Google returned
B1 =REGEXMATCH("abc123","\d+")

baseline: REGEXMATCH finds digits

Sanity check. If this fails, the harness itself is broken.

TRUE
B2 =REGEXEXTRACT("Order 4821 shipped","\d+")

baseline: REGEXEXTRACT pulls the first match

4821
B3 =REGEXREPLACE("John Smith","(\w+) (\w+)","$2 $1")

baseline: REGEXREPLACE swaps groups with $1 / $2

Dollar-sign backreferences are the Sheets replacement syntax.

Smith John
B4 =REGEXMATCH("abc123","abc(?=123)")

RE2 limit: positive lookahead (?=...)

Works on regex101. Here it is not #ERROR! — it is #REF!, the error people associate with a deleted cell reference. That is why they hunt for a typo that does not exist.

#REF!
B5 =REGEXMATCH("abc","a(?!b)")

RE2 limit: negative lookahead (?!...)

#REF!
B6 =REGEXMATCH("abc123","(?<=abc)123")

RE2 limit: lookbehind (?<=...)

#REF!
B7 =REGEXMATCH("abab","(ab)\1")

RE2 limit: backreference inside the pattern

Backreferences exist in the REPLACEMENT string of REGEXREPLACE, but never in the pattern.

#REF!
B8 =REGEXMATCH("héllo","\p{L}+")

Sheets limit: Unicode character class \p{L}

RE2 supports this. Google Sheets is the exception Google names in its own docs. This one catches people who already know RE2.

#REF!
B9 =REGEXMATCH("abc","(abc")

unbalanced parenthesis is also #REF!, not #ERROR!

A malformed regex and an unsupported one produce the same error. The cell tells you nothing about which.

#REF!
B10 =ERROR.TYPE(REGEXMATCH("abc123","abc(?=123)"))

cross-check: ERROR.TYPE of an unsupported pattern

Independent confirmation of the error type. ERROR.TYPE returns 4 for #REF!, 3 for #VALUE!, 7 for #N/A, 8 for #ERROR!. We do not take one measurement's word for it.

4
B11 =ERROR.TYPE(REGEXEXTRACT("abc","\d"))

cross-check: ERROR.TYPE of REGEXEXTRACT with no match

7
B12 =IFERROR(REGEXMATCH("abc123","abc(?=123)"),"caught")

an unsupported pattern is catchable with IFERROR

If IFERROR swallows it, a broken pattern can hide inside a working-looking spreadsheet forever.

caught
B13 =REGEXEXTRACT("abc","\d")

REGEXEXTRACT with no match

A different error from an invalid pattern. People wrap both in IFERROR without noticing.

#N/A
B14 =REGEXMATCH("cat dog","\bdog\b")

supported: word boundary \b

TRUE
B15 =REGEXEXTRACT("<a><b>","<(.+?)>")

supported: lazy quantifier +?

a
B16 =REGEXMATCH("ABC","(?i)abc")

supported: inline case-insensitive flag (?i)

TRUE
B17 =REGEXEXTRACT("x=1","(?P<digit>\d)")

supported: RE2 named capture group (?P<name>...)

RE2's own spelling.

1
B18 =REGEXEXTRACT("x=1","(?<digit>\d)")

supported: JavaScript named group syntax (?<name>...) also works

Measured, not assumed. Sheets accepts both spellings, and ignores the name either way — REGEXEXTRACT returns groups in order.

1
B19 =REGEXREPLACE("John Smith","(\w+) (\w+)","\2 \1")

trap: backslash backreference in the replacement string

No error. The backslashes vanish and you are left with the literal digits. Worse than an error, because an error tells you to stop.

2 1
B20 =REGEXREPLACE("abc","b","[$0]")

trap: $0 is the whole match in the replacement string

a[b]c
B21 =REGEXREPLACE("abc","b","[$1]")

trap: $1 when the pattern has no capture group

It is an error, not a silent empty string. We did not know, so we measured.

#N/A

Every row above was written into a real Google Sheet and read back through the Sheets API on 2026-07-09. The case file and this log are in the repository, and the build refuses to run if they disagree.

Why this page exists

Anyone can write that lookahead does not work in Google Sheets. It is in Google's documentation, one link away, and a language model will tell you the same thing in a second.

What almost nobody does is run it. So this page is the run. Each formula above was written into a cell through the Sheets API, and the value in the third column is what came back — not what we expected, not what the documentation says, not what a model predicted.

Some rows are marked observed. Those are cases where we did not know the answer beforehand, so we measured instead of asserting. Guessing and then presenting the guess as a finding is exactly the failure mode this site was built to avoid.

If any formula here changes what it does, the log goes stale and the site refuses to build. Tell us if you find one that is wrong before we do.