Skip to content

HF-131 (1/7): every interpreter cell error carries a message - #1761

Open
marcin-kordas-hoc wants to merge 5 commits into
developfrom
feat/hf-131-error-messages
Open

marcin-kordas-hoc wants to merge 5 commits into
developfrom
feat/hf-131-error-messages

Conversation

@marcin-kordas-hoc

@marcin-kordas-hoc marcin-kordas-hoc commented Sep 10, 2026

Copy link
Copy Markdown
Collaborator

What and why

HF-131 gives every cell error a real cause instead of just a type. This is the first of 7 stacked
PRs implementing that: every cell error thrown inside src/interpreter/ — 78 previously
message-less new CellError(...) sites across 15 source files — now carries an ErrorMessage constant
describing why it happened.

Nearly all 78 sites collapse into two shared constants (46 DIV_BY_ZERO sites, one constant; most
of the 26 NUM sites reuse an existing or lightly-new constant); six anomalies needed an
individually-authored message (Interpreter.ts, LookupPlugin.ts, FinancialPlugin.ts ×2,
InformationPlugin.ts).

Also adds an ESLint rule (no-restricted-syntax, scoped to src/interpreter/**/*.ts) so a
message-less new CellError(...) construction there is now a lint error — mechanical enforcement
that this guarantee can't silently regress. Widened to all of src/ in the next PR in this stack.

The public CellError constructor is unchangedmessage stays optional, for custom
functions. Only construction inside the engine's own src/ is now required to supply one.

Verified

  • npx tsc --noEmit — clean
  • npx eslint src/ — 0 errors (same pre-existing warning count as develop, no new warnings)
  • The ESLint rule was proven to actually fire, not just parse: a plugin site was temporarily
    reverted to a bare new CellError(ErrorType.NUM), confirmed to produce the expected lint error,
    then restored (git diff clean afterward)
  • Full private test suite (test/hyperformula-tests, --cacheDirectory isolated,
    --maxWorkers=2), reproduced against this branch's tip: no regressions beyond the pre-existing
    branch-pinning mismatch unrelated to this change (5 known failures on bare develop too)

Stack

1 of 7 — targets develop. Next: feat/hf-131-error-messages-outside-interpreter.

🤖 Generated with Claude Code


Note

Low Risk
Behavioral error types are unchanged; only optional detail messages are added plus lint guardrails in the interpreter. Low risk unless consumers assumed empty error messages.

Overview
HF-131 (1/7): Every CellError raised inside src/interpreter/ now includes a second-argument ErrorMessage describing why the error occurred, so engine-produced formula errors always expose a cause (changelog: #1547).

The change touches ~78 previously message-less new CellError(...) sites across the interpreter core and plugins (arithmetic, financial/IRR/XIRR, lookups, aggregations, trigonometry, etc.). Most #DIV/0! paths share ErrorMessage.DivisionByZero; other cases get new or existing constants (e.g. broadcast #N/A, MATCH search-range shape, NA(), rate/convergence messages). CellError’s public constructor is unchanged — optional message remains for custom functions.

Enforcement: ESLint no-restricted-syntax on src/interpreter/**/*.ts blocks CellError without a message (or with explicit undefined). error-message.ts gains the new shared strings.

Reviewed by Cursor Bugbot for commit c5b33cb. Bugbot is set up for automated code reviews on this repo. Configure here.

marcin-kordas-hoc and others added 2 commits September 7, 2026 16:46
Fills in all 78 call sites in src/interpreter/ that constructed a CellError
with no message, so a consumer no longer receives a bare #DIV/0! or #NUM! with
an empty message string.

Ten new catalogue entries in src/error-message.ts, not 78: the 46
division-by-zero sites share one ErrorMessage.DivisionByZero, and the 26 NUM
sites mostly reuse entries that already existed (ValueLarge, ValueSmall,
NotHex, NaN, BadMode, ComplexNumberExpected and others). New entries were added
only where nothing existing was accurate -- NoBroadcastValue,
SearchRangeDimension, NaFunction, TwoCashFlows, PositiveAndNegative,
NonZeroPeriods, NoConvergence, RateGuess, MaturityLong.

No error type changes and no signature changes; ArithmeticHelper.ts gains only
a message literal inside divide(). Nothing under src/i18n/ is touched -- this
slice is English-only by an explicit product decision.

Produced by a prep-ship (`spec-to-ship`) run: `prep-ship ship hf131-messages
--task-file ... --yes`. The run authored its acceptance specs first, then
iterated implementation against them. It was killed by a process restart
before reaching its own commit step, so this commit was made by hand from the
work it left in the worktree, after verifying it:

- 78 message-less sites -> 0, counted with the same command the task file gave.
- tsc --noEmit and eslint --quiet both clean.
- Full private suite: 5 failed / 6165 passed / 6173 total, against a baseline
  of 5 failed / 6157 passed / 6165 total. The 5 are a pre-existing test-repo
  branch-pinning mismatch, unrelated. The +8 are the run's own new specs, all
  passing.
- The run also updated three pre-existing specs whose expectations had gone
  stale (error-address-preservation, arrays, matrix-plugin). Checked each: it
  added the message argument to detailedErrorWithOrigin, which strengthens
  those assertions rather than weakening them -- they still compare the
  address, and now the message too, via catalogue constants. No test was
  loosened to reach green.

The ESLint rule that would stop a message-less CellError being reintroduced is
deliberately NOT here: the harness commits only src, docs and CHANGELOG.md, so
an .eslintrc.js change would have been silently dropped. It needs its own step.

Test-side changes live in the private repo and are not part of this commit.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Enforces the guarantee this PR's message-filling work establishes: a
message-less new CellError(...) construction under src/interpreter/ is now
a lint error. Two selectors — a bare one-argument call, and an explicit
literal undefined as the second argument (the exact shape the two CYCLE
sites in src/Evaluator.ts still use; Evaluator.ts is outside src/interpreter/
so this rule doesn't reach them yet, and is unaffected by this commit).

Verified: 0 lint errors on the full src/ tree (same pre-existing warning
count as before this commit — no new warnings). The rule was proven to
actually fire, not just parse, by temporarily reverting one src/interpreter/
plugin site to a bare 'new CellError(ErrorType.NUM)', observing the expected
lint error, then restoring it (git diff empty afterward).

Widened to all of src/ in the next PR in this stack
(feat/hf-131-error-messages-outside-interpreter).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@qunabu

qunabu commented Sep 10, 2026

Copy link
Copy Markdown
Contributor

@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Sep 10, 2026

Copy link
Copy Markdown

Deploying with  Cloudflare Workers  Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

Status Name Latest Commit Preview URL Updated (UTC)
✅ Deployment successful!
View logs
hyperformula-docs c5b33cb Commit Preview URL

Branch Preview URL
Sep 14 2026, 10:11 AM

@cursor cursor 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.

Cursor Bugbot has reviewed your changes using default effort and found 2 potential issues.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 84708e2. Configure here.

Comment thread CHANGELOG.md Outdated
Comment thread .eslintrc.js
…messages

# Conflicts:
#	CHANGELOG.md
#	src/error-message.ts
#	src/interpreter/plugin/ConditionalAggregationPlugin.ts
#	src/interpreter/plugin/ModuloPlugin.ts
@github-actions

github-actions Bot commented Sep 11, 2026

Copy link
Copy Markdown

Performance comparison of head (c5b33cb) vs base (c920375)

                                     testName |    base |    head | change
--------------------------------------------------------------------------
                                      Sheet A |  453.13 |  448.91 | -0.93%
                                      Sheet B |  139.58 |  138.86 | -0.52%
                                      Sheet T |  122.05 |  122.37 | +0.26%
                                Column ranges |  589.11 |  579.72 | -1.59%
                                Sorted lookup | 16972.1 | 16796.9 | -1.03%
Sheet A:  change value, add/remove row/column |   12.78 |   13.31 | +4.15%
 Sheet B: change value, add/remove row/column |  114.44 |  117.67 | +2.82%
                   Column ranges - add column |  157.24 |  156.69 | -0.35%
                Column ranges - without batch |  496.78 |  487.55 | -1.86%
                        Column ranges - batch |  124.18 |  120.64 | -2.85%

marcin-kordas-hoc and others added 2 commits September 11, 2026 05:30
No engine changes -- the paired hyperformula-tests branch for this PR
gained 4 new coverage-closing test cases after the initial CI run, and
re-running the same commit isn't possible; this empty commit forces a
fresh run so codecov/patch reflects them.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
HF-131 is a ClickUp id; GitHub #131 is an unrelated, closed issue about array
type support. The work this stack does is tracked by #1547.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@codecov

codecov Bot commented Sep 14, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 98.87640% with 1 line in your changes missing coverage. Please review.
✅ Project coverage is 97.36%. Comparing base (c920375) to head (c5b33cb).

Files with missing lines Patch % Lines
src/interpreter/plugin/FinancialPlugin.ts 97.29% 1 Missing ⚠️
Additional details and impacted files

Impacted file tree graph

@@             Coverage Diff             @@
##           develop    #1761      +/-   ##
===========================================
+ Coverage    97.32%   97.36%   +0.03%     
===========================================
  Files          195      195              
  Lines        15739    15750      +11     
  Branches      3390     3461      +71     
===========================================
+ Hits         15318    15335      +17     
+ Misses         421      407      -14     
- Partials         0        8       +8     
Files with missing lines Coverage Δ
src/error-message.ts 100.00% <100.00%> (ø)
src/interpreter/ArithmeticHelper.ts 98.67% <100.00%> (ø)
src/interpreter/Interpreter.ts 95.36% <100.00%> (ø)
src/interpreter/plugin/ComplexPlugin.ts 100.00% <100.00%> (ø)
...interpreter/plugin/ConditionalAggregationPlugin.ts 100.00% <100.00%> (ø)
src/interpreter/plugin/DatabasePlugin.ts 95.25% <100.00%> (ø)
src/interpreter/plugin/InformationPlugin.ts 93.33% <100.00%> (ø)
src/interpreter/plugin/LookupPlugin.ts 97.26% <100.00%> (ø)
src/interpreter/plugin/MathPlugin.ts 100.00% <100.00%> (ø)
src/interpreter/plugin/ModuloPlugin.ts 100.00% <100.00%> (ø)
... and 6 more

... and 5 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@Tobiadefami Tobiadefami left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Looks good. Verified the added error messages and that the lint rule rejects both missing messages and explicit undefined.

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.

3 participants