Skip to content

Fix error string from #N/A! to #N/A#101

Merged
hackerwins merged 2 commits into
mainfrom
change-error-n/a
Apr 1, 2026
Merged

Fix error string from #N/A! to #N/A#101
hackerwins merged 2 commits into
mainfrom
change-error-n/a

Conversation

@ggyuchive

@ggyuchive ggyuchive commented Apr 1, 2026

Copy link
Copy Markdown
Member

Summary

Wafflebase return error #N/A! when function return no applicable result (missing args), but google sheet/excel returns #N/A. It changes to return #N/A.

Why

Compatible error string with google sheet.

Linked Issues

Fixes #

Verification

CI automatically posts a verification summary comment on this PR with
per-lane results for both verify:self and verify:integration.

  • verify:self — CI comment shows ✅
  • verify:integration — CI comment shows ✅ (or explicit skip reason below)

Skip reason (if applicable):

Risk Assessment

  • User-facing risk:
  • Data/security risk:
  • Rollback plan:

Notes for Reviewers

  • UI changes (screenshots/gifs if applicable):
  • Follow-up work (if any):

Summary by CodeRabbit

  • Bug Fixes

    • Standardized the "not available" error token from "#N/A!" to "#N/A" across formulas, UI scenarios, and tests for consistent display and handling.
  • Documentation

    • Updated error documentation and the Error Types table to use "#N/A" and to include "#DIV/0!" as a listed error type.

@coderabbitai

coderabbitai Bot commented Apr 1, 2026

Copy link
Copy Markdown

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 9310a68d-a1de-4689-8c28-5045d5b42365

📥 Commits

Reviewing files that changed from the base of the PR and between c45996d and 8e71f5f.

⛔ Files ignored due to path filters (8)
  • packages/frontend/tests/visual/baselines/harness-visual.browser.desktop.dark.png is excluded by !**/*.png
  • packages/frontend/tests/visual/baselines/harness-visual.browser.mobile.dark.png is excluded by !**/*.png
  • packages/frontend/tests/visual/baselines/harness-visual.browser.mobile.png is excluded by !**/*.png
  • packages/frontend/tests/visual/baselines/harness-visual.browser.png is excluded by !**/*.png
  • packages/frontend/tests/visual/baselines/harness-visual.browser.sheet-formula-errors.desktop.dark.png is excluded by !**/*.png
  • packages/frontend/tests/visual/baselines/harness-visual.browser.sheet-formula-errors.mobile.dark.png is excluded by !**/*.png
  • packages/frontend/tests/visual/baselines/harness-visual.browser.sheet-formula-errors.mobile.png is excluded by !**/*.png
  • packages/frontend/tests/visual/baselines/harness-visual.browser.sheet-formula-errors.png is excluded by !**/*.png
📒 Files selected for processing (1)
  • docs/design/formula.md
✅ Files skipped from review due to trivial changes (1)
  • docs/design/formula.md

📝 Walkthrough

Walkthrough

This pull request standardizes the spreadsheet "not available" error token from #N/A! to #N/A across types, implementations, documentation, visual fixtures, and tests. No evaluation control flow or public API signatures were changed.

Changes

Cohort / File(s) Summary
Core Type & Engine
packages/sheets/src/formula/formula.ts
Updated ErrNode union to use '#N/A' instead of '#N/A!'.
Docs & Tasks
docs/design/formula.md, docs/tasks/archive/2026/02/20260227-harness-phase18-sheet-visual-baselines-todo.md
Replaced #N/A! with #N/A in documentation and checklist text.
Frontend Visual Fixture
packages/frontend/src/app/harness/visual/sheet-scenarios.tsx
Adjusted scenario description and fixture cell B5 expected text from #N/A!#N/A.
Function Catalog
packages/sheets/src/formula/function-catalog.ts
Updated user-facing function descriptions to reference #N/A (ISERR, ISNA, IFNA, NA).
Database Functions
packages/sheets/src/formula/functions-database.ts
extractDatabaseValues now returns '#N/A' for missing/invalid args.
Date/Time Functions
packages/sheets/src/formula/functions-date.ts
Replaced '#N/A!' with '#N/A' across date/time functions for missing/invalid-arg branches.
Engineering Functions
packages/sheets/src/formula/functions-engineering.ts
Replaced '#N/A!' with '#N/A' across engineering, base/bitwise, complex, and related helpers.
Financial Functions
packages/sheets/src/formula/functions-financial.ts
Replaced '#N/A!' with '#N/A' across many financial worksheet functions for arg validation failures.
Information & Type Functions
packages/sheets/src/formula/functions-info.ts
Replaced '#N/A!' with '#N/A' in returns/comparisons, updated ERROR.TYPE mapping key and related checks.
Logical Functions
packages/sheets/src/formula/functions-logical.ts
Replaced '#N/A!' with '#N/A' in logical/branching functions; adjusted ifna error detection to match new token.
Lookup & Array Functions
packages/sheets/src/formula/functions-lookup.ts
Replaced '#N/A!' with '#N/A' across lookup, index, indirect/offset, and array transform functions.
Math Functions
packages/sheets/src/formula/functions-math.ts
Replaced '#N/A!' with '#N/A' for argument-validation error returns across many math helpers.
Statistical Functions
packages/sheets/src/formula/functions-statistical.ts
Replaced '#N/A!' with '#N/A' in statistical functions and paired-array helper error returns.
Text Functions
packages/sheets/src/formula/functions-text.ts
Replaced '#N/A!' with '#N/A' for missing/invalid-arg and "not found" branches in text/regex helpers.
Tests
packages/sheets/test/formula/formula.test.ts
Updated unit test expectations from '#N/A!' to '#N/A' across multiple assertions.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Poem

🐰 I hopped through docs and through each file,
I nudged a stray exclamation off the pile.
From #N/A! to #N/A — neat and small,
Across tests, functions, and the docs I scrolled.
A tiny trim, a tidy hop — hooray!

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the primary change: replacing the error string #N/A! with #N/A across the codebase for Excel/Google Sheets compatibility.
Docstring Coverage ✅ Passed Docstring coverage is 99.73% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch change-error-n/a

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions

github-actions Bot commented Apr 1, 2026

Copy link
Copy Markdown
Contributor

Verification: verify:self

Result: ✅ PASS in 108.0s

Lane Status Duration
sheets:build ✅ pass 13.4s
docs:build ✅ pass 6.4s
verify:fast ✅ pass 54.5s
frontend:build ✅ pass 14.7s
verify:frontend:chunks ✅ pass 0.3s
backend:build ✅ pass 4.3s
cli:build ✅ pass 1.8s
verify:entropy ✅ pass 12.6s

Verification: verify:integration

Result: ✅ PASS

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (4)
packages/sheets/src/formula/functions-date.ts (2)

450-489: ⚠️ Potential issue | 🟠 Major

NETWORKDAYS currently ignores the advertised holidays argument.

Arity allows three arguments here, but exprs[2] is never consumed, so NETWORKDAYS(start, end, holidays) silently returns a weekend-only count. Either implement holiday exclusion here or reject the third argument for now.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/sheets/src/formula/functions-date.ts` around lines 450 - 489,
networkdaysFunc currently ignores exprs[2] (holidays); either reject the third
arg or implement holiday exclusion—prefer implementing: when exprs.length === 3
call visit(exprs[2]) and convert the result into a set of Date-only keys (use
parseDate for single values and handle arrays/ranges by iterating elements) then
when iterating days in networkdaysFunc skip any date whose Date-only key exists
in that holidays set; ensure you still use parseDate for start/end and return
the same error node if any holiday entries fail to parse.

496-545: ⚠️ Potential issue | 🟠 Major

Propagate optional-argument errors instead of defaulting.

NETWORKDAYS.INTL, WORKDAY.INTL, and DAYS360 fall back to default weekend/method values when the optional argument evaluates to an error. Formulas like WORKDAY.INTL(A1, 1, NA()) should surface #N/A, not return a computed result.

Also applies to: 850-903, 1011-1048

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/sheets/src/formula/functions-date.ts` around lines 496 - 545, In
networkdaysintlFunc, optional-argument evaluation errors are being swallowed and
the function falls back to defaults; ensure any error node from evaluating the
optional weekend or holidays arguments is propagated instead of defaulting: if
NumberArgs.map(visit(exprs[2]), grid) yields a node with t === 'err', return
that node immediately (do not call getWeekendDays), and likewise if
visit(exprs[3]) yields a node with t === 'err' return it (do not try to treat it
as a ref); apply the same pattern to the analogous handling in WORKDAY.INTL and
DAYS360 (the other ranges you noted) so optional-argument errors bubble up.
packages/sheets/src/formula/functions-engineering.ts (1)

653-673: ⚠️ Potential issue | 🟠 Major

COMPLEX(..., "j") still does not round-trip through the IM* functions.

This branch can emit values like 1+2j, but the shared complex parser only recognizes i, so IMREAL(COMPLEX(1,2,"j")) and the other IM* helpers still fail with #VALUE!. Normalize j before returning here, or teach parseComplex to accept both suffixes.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/sheets/src/formula/functions-engineering.ts` around lines 653 - 673,
The COMPLEX handling in complexFunc can emit a "j" suffix which downstream
functions (e.g., parseComplex used by IMREAL/IMAG/IMABS) don't recognize; update
complexFunc so after obtaining suffix from toStr(visit(exprs[2]), grid) it
normalizes 'j' to 'i' (e.g., if sNode.v === 'j' set suffix = 'i') before
returning, while still validating only 'i' or 'j'; reference complexFunc, toStr,
NumberArgs.map (and parseComplex for context) to locate where to normalize.
packages/sheets/src/formula/functions-text.ts (1)

1136-1216: ⚠️ Potential issue | 🟠 Major

Add a comment explaining why direct regex compilation from formula input is unsafe.

The REGEXMATCH, REGEXEXTRACT, and REGEXREPLACE functions accept user-supplied regex patterns that are compiled directly via new RegExp(pattern.v). A pathological pattern—for example, (a+)+b—can trigger catastrophic backtracking and hang the evaluator thread indefinitely, with no recovery. The existing try-catch only guards against syntax errors (e.g., unclosed brackets), not ReDoS attacks. Consider restricting regex features or implementing complexity validation before compilation.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/sheets/src/formula/functions-text.ts` around lines 1136 - 1216, The
three functions regexmatchFunc, regexextractFunc, and regexreplaceFunc compile
user-supplied patterns directly with new RegExp(pattern.v), which leaves the
evaluator vulnerable to catastrophic backtracking / ReDoS; update these
functions to validate or sandbox patterns before compilation by (a) enforcing a
max pattern length, rejecting patterns containing known-dangerous constructs
(e.g. nested quantifiers like (.+)+, (a+)+, excessive backreferences or
lookaround combos), or (b) using a safe regex strategy such as a
pre-compiled/safe-regex library or running the RegExp execution inside a
time-limited worker/timeout and returning an error on timeout; ensure the
validation/sandbox is applied in regexmatchFunc, regexextractFunc and
regexreplaceFunc prior to calling new RegExp and that failures return a
consistent error (e.g. '#VALUE!') to avoid hanging the evaluator.
🧹 Nitpick comments (1)
packages/sheets/src/formula/formula.ts (1)

496-499: Consider promoting error tokens to shared constants.

This PR had to update the same literal in multiple files, and one missed runtime comparison would leave checks like IFNA/ISNA out of sync with returned values. A single exported source of truth here would make future token changes mechanical.

♻️ Suggested shape
+export const ERROR_VALUES = {
+  VALUE: '#VALUE!',
+  REF: '#REF!',
+  NA: '#N/A',
+  ERROR: '#ERROR!',
+  DIV0: '#DIV/0!',
+} as const;
+
 export type ErrNode = {
   t: 'err';
-  v: '#VALUE!' | '#REF!' | '#N/A' | '#ERROR!' | '#DIV/0!';
+  v: (typeof ERROR_VALUES)[keyof typeof ERROR_VALUES];
 };
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/sheets/src/formula/formula.ts` around lines 496 - 499, Replace the
inline error literal union in ErrNode with a single exported set of error token
constants and use those constants everywhere; specifically, add exported
constants (e.g., ERR_VALUE, ERR_REF, ERR_NA, ERR_ERROR, ERR_DIV0) and change
ErrNode.v to reference those constants (either via a union of typeof CONSTANTs
or a shared ErrorTokens type), then update all places that construct or compare
error nodes (functions that return ErrNode and checks like IFNA/ISNA) to use the
exported constants instead of raw string literals so all runtime comparisons and
returns come from the same source of truth.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@docs/design/formula.md`:
- Around line 102-103: The ErrNode documentation's union of error strings is
missing "#DIV/0!" which differs from the engine's error type; update the ErrNode
declaration (`ErrNode { t: 'err', v: ... }`) to include "#DIV/0!" in the union
of documented values (and update the other occurrence noted around the second
block at lines ~183-184) so the docs match the engine's error set and remove
potential confusion for contributors.

---

Outside diff comments:
In `@packages/sheets/src/formula/functions-date.ts`:
- Around line 450-489: networkdaysFunc currently ignores exprs[2] (holidays);
either reject the third arg or implement holiday exclusion—prefer implementing:
when exprs.length === 3 call visit(exprs[2]) and convert the result into a set
of Date-only keys (use parseDate for single values and handle arrays/ranges by
iterating elements) then when iterating days in networkdaysFunc skip any date
whose Date-only key exists in that holidays set; ensure you still use parseDate
for start/end and return the same error node if any holiday entries fail to
parse.
- Around line 496-545: In networkdaysintlFunc, optional-argument evaluation
errors are being swallowed and the function falls back to defaults; ensure any
error node from evaluating the optional weekend or holidays arguments is
propagated instead of defaulting: if NumberArgs.map(visit(exprs[2]), grid)
yields a node with t === 'err', return that node immediately (do not call
getWeekendDays), and likewise if visit(exprs[3]) yields a node with t === 'err'
return it (do not try to treat it as a ref); apply the same pattern to the
analogous handling in WORKDAY.INTL and DAYS360 (the other ranges you noted) so
optional-argument errors bubble up.

In `@packages/sheets/src/formula/functions-engineering.ts`:
- Around line 653-673: The COMPLEX handling in complexFunc can emit a "j" suffix
which downstream functions (e.g., parseComplex used by IMREAL/IMAG/IMABS) don't
recognize; update complexFunc so after obtaining suffix from
toStr(visit(exprs[2]), grid) it normalizes 'j' to 'i' (e.g., if sNode.v === 'j'
set suffix = 'i') before returning, while still validating only 'i' or 'j';
reference complexFunc, toStr, NumberArgs.map (and parseComplex for context) to
locate where to normalize.

In `@packages/sheets/src/formula/functions-text.ts`:
- Around line 1136-1216: The three functions regexmatchFunc, regexextractFunc,
and regexreplaceFunc compile user-supplied patterns directly with new
RegExp(pattern.v), which leaves the evaluator vulnerable to catastrophic
backtracking / ReDoS; update these functions to validate or sandbox patterns
before compilation by (a) enforcing a max pattern length, rejecting patterns
containing known-dangerous constructs (e.g. nested quantifiers like (.+)+,
(a+)+, excessive backreferences or lookaround combos), or (b) using a safe regex
strategy such as a pre-compiled/safe-regex library or running the RegExp
execution inside a time-limited worker/timeout and returning an error on
timeout; ensure the validation/sandbox is applied in regexmatchFunc,
regexextractFunc and regexreplaceFunc prior to calling new RegExp and that
failures return a consistent error (e.g. '#VALUE!') to avoid hanging the
evaluator.

---

Nitpick comments:
In `@packages/sheets/src/formula/formula.ts`:
- Around line 496-499: Replace the inline error literal union in ErrNode with a
single exported set of error token constants and use those constants everywhere;
specifically, add exported constants (e.g., ERR_VALUE, ERR_REF, ERR_NA,
ERR_ERROR, ERR_DIV0) and change ErrNode.v to reference those constants (either
via a union of typeof CONSTANTs or a shared ErrorTokens type), then update all
places that construct or compare error nodes (functions that return ErrNode and
checks like IFNA/ISNA) to use the exported constants instead of raw string
literals so all runtime comparisons and returns come from the same source of
truth.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 74a7f565-3323-49b5-be12-a51e5d758594

📥 Commits

Reviewing files that changed from the base of the PR and between e189de3 and c45996d.

📒 Files selected for processing (16)
  • docs/design/formula.md
  • docs/tasks/archive/2026/02/20260227-harness-phase18-sheet-visual-baselines-todo.md
  • packages/frontend/src/app/harness/visual/sheet-scenarios.tsx
  • packages/sheets/src/formula/formula.ts
  • packages/sheets/src/formula/function-catalog.ts
  • packages/sheets/src/formula/functions-database.ts
  • packages/sheets/src/formula/functions-date.ts
  • packages/sheets/src/formula/functions-engineering.ts
  • packages/sheets/src/formula/functions-financial.ts
  • packages/sheets/src/formula/functions-info.ts
  • packages/sheets/src/formula/functions-logical.ts
  • packages/sheets/src/formula/functions-lookup.ts
  • packages/sheets/src/formula/functions-math.ts
  • packages/sheets/src/formula/functions-statistical.ts
  • packages/sheets/src/formula/functions-text.ts
  • packages/sheets/test/formula/formula.test.ts

Comment thread docs/design/formula.md Outdated
@hackerwins

Copy link
Copy Markdown
Collaborator

Visual baseline update needed

This PR changes the #N/A! error string to #N/A, which affects the rendered output in the sheet-formula-errors visual scenario. The 4 baseline screenshots need to be regenerated so that the visual regression tests pass:

  • sheet-formula-errors.png (desktop light)
  • sheet-formula-errors.desktop.dark.png
  • sheet-formula-errors.mobile.png
  • sheet-formula-errors.mobile.dark.png

How to update (pick one):

# Option A — run locally with Docker (recommended, matches CI environment)
pnpm frontend test:visual:browser:docker:update

# Option B — run locally without Docker (needs a Chromium-compatible browser)
pnpm frontend test:visual:browser:update

This will re-capture all visual baselines. Commit the updated .png files under packages/frontend/tests/visual/baselines/ into this branch.

After that, you can verify everything passes with:

pnpm verify:browser:docker

@hackerwins
hackerwins merged commit 85f7df9 into main Apr 1, 2026
3 checks passed
@hackerwins
hackerwins deleted the change-error-n/a branch April 1, 2026 23:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants