Skip to content

Fix parse errors being overwritten by disposal errors in runWith() and runWithSync()#771

Merged
dahlia merged 8 commits intomainfrom
issue-246-suppress-dispose-error
Apr 4, 2026
Merged

Fix parse errors being overwritten by disposal errors in runWith() and runWithSync()#771
dahlia merged 8 commits intomainfrom
issue-246-suppress-dispose-error

Conversation

@dahlia
Copy link
Copy Markdown
Owner

@dahlia dahlia commented Apr 4, 2026

When parsing fails in runWith() or runWithSync() and a source context also throws during disposal, the disposal error silently replaces the original parse error. This happens because JavaScript's try/finally semantics cause the finally error to take precedence over the try error.

For example, given a context whose Symbol.dispose throws and a parser that receives invalid input:

const context: SourceContext = {
  id: Symbol.for("@myapp/ctx"),
  getAnnotations() { return {}; },
  [Symbol.dispose]() { throw new Error("dispose failed."); },
};

try {
  runWithSync(parser, "test", [context], { args: ["not-a-number"] });
} catch (error) {
  // Before: error.message === "dispose failed."  (parse error lost)
  // After:  error is a SuppressedError preserving both failures
}

This PR restructures the error handling in both runWith() and runWithSync() to preserve the original parse error when disposal also throws. The parsing body is extracted into helper functions (runWithBody and runWithSyncBody) in packages/core/src/facade.ts, and the callers handle disposal explicitly outside try/finally blocks. When both parsing and disposal fail, the errors are wrapped in a SuppressedError following TC39 conventions: .error contains the disposal error (the newer error) and .suppressed contains the original parse error.

Since SuppressedError is only available as a global starting from Node 24, but the package supports node >=20, a local polyfill is included that provides the same interface on older runtimes.

Closes #246

dahlia and others added 3 commits April 4, 2026 11:20
When parsing fails in runWith() or runWithSync() and a source context's
disposal also throws, the disposal error used to silently replace the
original parse error due to JavaScript's try/finally semantics.

The disposal error now wraps both failures in a SuppressedError
(following TC39 conventions) instead of discarding the parse error:

- .error = the disposal error (the newer error)
- .suppressed = the original parse error

The try/finally blocks were restructured into helper functions
(runWithBody, runWithSyncBody) with explicit error handling in the
callers, avoiding the no-unsafe-finally lint issue entirely.

#246

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
SuppressedError is only a global starting from Node 24, but the
package supports Node >= 20.  Add a local polyfill so the
double-failure disposal path works correctly on all supported
runtimes instead of throwing ReferenceError.

#246

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@dahlia dahlia requested a review from Copilot April 4, 2026 02:40
@dahlia dahlia self-assigned this Apr 4, 2026
@dahlia dahlia added the bug Something isn't working label Apr 4, 2026
@dahlia dahlia added this to the Optique 1.0 milestone Apr 4, 2026
@codecov
Copy link
Copy Markdown

codecov Bot commented Apr 4, 2026

Codecov Report

❌ Patch coverage is 91.70732% with 17 lines in your changes missing coverage. Please review.
✅ Project coverage is 91.14%. Comparing base (85e1e6a) to head (73dd4e3).
⚠️ Report is 9 commits behind head on main.
✅ All tests successful. No failed tests found.

Files with missing lines Patch % Lines
packages/core/src/facade.ts 91.70% 17 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #771      +/-   ##
==========================================
+ Coverage   91.07%   91.14%   +0.07%     
==========================================
  Files          43       43              
  Lines       25249    25317      +68     
  Branches     6473     6493      +20     
==========================================
+ Hits        22995    23075      +80     
+ Misses       2175     2165      -10     
+ Partials       79       77       -2     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 797077471d

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread packages/core/src/facade.test.ts Outdated
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR fixes an error-reporting edge case in @optique/core’s runWith() / runWithSync() where a context disposal failure could overwrite (and effectively hide) the original parse failure. It restructures the control flow to dispose contexts outside of try/finally so both failures can be preserved via SuppressedError.

Changes:

  • Refactors parsing logic into runWithBody() / runWithSyncBody() and performs disposal in an explicit post-parse step.
  • Wraps parse+dispose double-failures using SuppressedError semantics (error = disposal error, suppressed = parse error), with a local constructor fallback.
  • Adds regression tests for suppressed disposal errors and updates CHANGES.md.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 4 comments.

File Description
packages/core/src/facade.ts Refactors runWith* flow and introduces SuppressedError constructor fallback + explicit suppression behavior.
packages/core/src/facade.test.ts Adds tests asserting SuppressedError behavior for parse failure + disposal failure combinations.
CHANGES.md Documents the fix and links the issue/PR.

Comment thread packages/core/src/facade.ts
Comment thread packages/core/src/facade.test.ts Outdated
Comment thread packages/core/src/facade.ts
Comment thread packages/core/src/facade.ts
Copy link
Copy Markdown

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request fixes a bug where parse errors were discarded if context disposal also failed. It introduces a SuppressedError polyfill for compatibility with older runtimes and refactors runWith and runWithSync to ensure all failures are preserved. The review feedback suggests simplifying the code by removing redundant type assertions when accessing contextOptions.

Comment thread packages/core/src/facade.ts Outdated
Comment thread packages/core/src/facade.ts Outdated
dahlia and others added 2 commits April 4, 2026 11:49
Replace `instanceof SuppressedError` with duck-typing on
`.name`/`.error`/`.suppressed` so the assertions don't depend on
a global `SuppressedError` constructor.

#771 (comment)
#771 (comment)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Remove redundant casts; RunWithOptions already declares
contextOptions as an optional property.

#771 (comment)
#771 (comment)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 4, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: d9a50d3f-c6de-43ad-a232-780d8256c7d8

📥 Commits

Reviewing files that changed from the base of the PR and between badbb89 and 73dd4e3.

📒 Files selected for processing (1)
  • packages/core/src/facade.ts

Walkthrough

Refactors parsing/annotation flow into new helpers (runWithBody / runWithSyncBody), centralizes two-phase parsing for dynamic contexts, and adds a runtime SuppressedError constructor/polyfill. runWith and runWithSync now capture any primary runner/parse error, always execute context disposal, and if disposal subsequently throws they wrap disposal errors with the original error using SuppressedError (or AggregateError for multiple disposal failures) instead of replacing the parse error. Adds synchronous and asynchronous tests for parse+dispose failure interactions and updates CHANGES.md and JSDoc to document the behavior.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main change: fixing parse errors being overwritten by disposal errors in runWith() and runWithSync().
Description check ✅ Passed The description provides clear context about the problem, demonstrates the issue with code examples, and explains the solution using SuppressedError wrapping.
Linked Issues check ✅ Passed The PR addresses issue #246 by restructuring error handling in runWith() and runWithSync() to preserve parse errors when disposal also throws, wrapping both in a SuppressedError.
Out of Scope Changes check ✅ Passed All changes are within scope: facade.ts refactored for error handling, tests added for SuppressedError behavior, and CHANGES.md updated to document the fix.
Docstring Coverage ✅ Passed Docstring coverage is 83.33% 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 docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch issue-246-suppress-dispose-error

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.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/core/src/facade.test.ts`:
- Line 6327: Replace uses of "error instanceof SuppressedError" in the tests
with a shape/name-based assertion so tests don't rely on the global
SuppressedError; for each occurrence (e.g. the assert.ok(error instanceof
SuppressedError) checks) assert that error is an object, error.name ===
'SuppressedError' (or error?.name === 'SuppressedError') and that the expected
suppressed property exists (e.g. Array.isArray(error.suppressed) or 'suppressed'
in error) — update all occurrences noted (the assert.ok(...) checks at the
listed locations) to use this guard pattern.

In `@packages/core/src/facade.ts`:
- Around line 3047-3057: The JSDoc for the public API was left on the private
helper runWithBody; move that docblock back onto the exported runWith function,
ensuring the exported runWith has full description, `@param`, `@returns` and the
`@since` tag (remove `@since` from runWithBody). Update the `@throws` block on runWith
to mention the new SuppressedError path (describe when SuppressedError is thrown
and include it alongside existing error cases). Repeat the same
relocation/update for the other occurrence referenced (lines around the
runWith/runWithBody pair at 3202-3214) so only exported symbols carry `@since` and
public docs.
- Around line 3229-3255: The current flow only treats thrown exceptions from
runWithBody/runWithSyncBody as "primary" errors, so parse failures returned via
runParser's configured onError are treated as success and can be overwritten by
disposal errors; update the body helpers (runWithBody and runWithSyncBody) to
return a discriminated outcome that distinguishes a successful result, a thrown
exception, and a "handled parse failure" (the onError return), then in this code
use that discriminator instead of hasPrimaryError: capture the
handled-parse-failure outcome (e.g., hasHandledParseFailure + handledValue)
alongside thrown primaryError, call disposeContexts, and if dispose throws
prefer wrapping the disposeError with SuppressedErrorCtor using the original
primary/handled outcome as the suppressed value so the configured parse-failure
result is not lost; adjust downstream logic that currently checks
hasPrimaryError to also consider the handled-parse-failure branch.
🪄 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: Repository UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: ce8ec5bf-4360-44bc-841b-2b919a255ff1

📥 Commits

Reviewing files that changed from the base of the PR and between 85e1e6a and 7970774.

📒 Files selected for processing (3)
  • CHANGES.md
  • packages/core/src/facade.test.ts
  • packages/core/src/facade.ts

Comment thread packages/core/src/facade.test.ts Outdated
Comment thread packages/core/src/facade.ts
Comment thread packages/core/src/facade.ts
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Caution

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

⚠️ Outside diff range comments (1)
packages/core/src/facade.ts (1)

3359-3365: 🛠️ Refactor suggestion | 🟠 Major

Update @throws to include SuppressedError.

The function can now throw SuppressedError when both parsing and disposal fail. The JSDoc @throws section should document this new error type for completeness.

📝 Suggested documentation update
  * `@throws` {TypeError} If an async parser is passed at runtime.  Use
  * {`@link` runWith} or {`@link` runWithAsync} for async parsers.
  * `@throws` {TypeError} If two or more contexts share the same
  * {`@link` SourceContext.id}.
  * `@throws` {Error} If any context returns a Promise or if a context's
  * `[Symbol.asyncDispose]` returns a Promise.
+ * `@throws` {SuppressedError} If parsing fails and context disposal also
+ * throws.  The disposal error is in `.error` and the parse error in
+ * `.suppressed`.

As per coding guidelines, functions that throw exceptions must include the @throws tag documenting all thrown error types.

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

In `@packages/core/src/facade.ts` around lines 3359 - 3365, Update the JSDoc
`@throws` block in the affected facade function to list SuppressedError in
addition to the existing error types: add a line like "@throws {SuppressedError}
If both parsing and disposal fail and an aggregate suppressed error is produced"
so the documentation reflects that the function can throw SuppressedError when a
parser error and a disposal ([Symbol.asyncDispose]) error occur (alongside the
existing TypeError and Error notes referencing async parsers, SourceContext.id
collisions, and Promise-returning contexts). Ensure the new `@throws` entry
appears with the other `@throws` tags near the runWith/runWithAsync related JSDoc.
♻️ Duplicate comments (2)
packages/core/src/facade.ts (2)

3047-3057: 🛠️ Refactor suggestion | 🟠 Major

JSDoc is on the internal helper instead of the exported function.

The JSDoc block (including @since 0.10.0, @example, and @throws) is currently documenting runWithBody() rather than the exported runWith(). Per coding guidelines, exported APIs must have JSDoc comments, and based on learnings, only publicly exported API symbols should carry the @since tag.

Additionally, the @throws documentation should be updated to include SuppressedError for the new disposal error handling path.

Also applies to: 3200-3214

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

In `@packages/core/src/facade.ts` around lines 3047 - 3057, The JSDoc currently
annotates the internal helper runWithBody instead of the exported runWith; move
the full JSDoc block (including `@since` 0.10.0, `@example` and `@throws`) from
runWithBody to the exported runWith function, remove the `@since` tag from any
non-exported/internal symbols, and update the `@throws` list to mention both the
original errors and SuppressedError to cover the new disposal error path; also
apply the same relocation/update for the duplicate JSDoc instance that documents
the internal helper referenced around the other occurrence (the later block
covering the same behavior).

3227-3255: ⚠️ Potential issue | 🟡 Minor

Parse failures handled via onError callback return are not preserved when disposal throws.

When runParser() reports a parse failure by returning the configured onError value (rather than throwing), runWithBody() returns normally and hasPrimaryError stays false. If disposal subsequently throws, only the disposal error propagates—the parse-failure return value is lost.

This is primarily an edge case (common patterns like onError: process.exit terminate before disposal), but for handlers that return values, the original outcome is overwritten.

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

In `@packages/core/src/facade.ts` around lines 3227 - 3255, The code only treats
thrown errors from runWithBody as the "primary" outcome; to preserve
parse-failure returns you must mark and preserve the successful result as a
primary outcome as well: after calling runWithBody set a hasPrimaryResult (or
reuse hasPrimaryError semantics inverted) and store result; in the
disposeContexts catch, if a primary result exists then do not let the disposal
error overwrite it—return the preserved result (or wrap the disposal error as
suppressed but keep returning the original result) instead of throwing; update
the logic around runWithBody, result, hasPrimaryError, and disposeContexts to
implement this behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In `@packages/core/src/facade.ts`:
- Around line 3359-3365: Update the JSDoc `@throws` block in the affected facade
function to list SuppressedError in addition to the existing error types: add a
line like "@throws {SuppressedError} If both parsing and disposal fail and an
aggregate suppressed error is produced" so the documentation reflects that the
function can throw SuppressedError when a parser error and a disposal
([Symbol.asyncDispose]) error occur (alongside the existing TypeError and Error
notes referencing async parsers, SourceContext.id collisions, and
Promise-returning contexts). Ensure the new `@throws` entry appears with the other
`@throws` tags near the runWith/runWithAsync related JSDoc.

---

Duplicate comments:
In `@packages/core/src/facade.ts`:
- Around line 3047-3057: The JSDoc currently annotates the internal helper
runWithBody instead of the exported runWith; move the full JSDoc block
(including `@since` 0.10.0, `@example` and `@throws`) from runWithBody to the exported
runWith function, remove the `@since` tag from any non-exported/internal symbols,
and update the `@throws` list to mention both the original errors and
SuppressedError to cover the new disposal error path; also apply the same
relocation/update for the duplicate JSDoc instance that documents the internal
helper referenced around the other occurrence (the later block covering the same
behavior).
- Around line 3227-3255: The code only treats thrown errors from runWithBody as
the "primary" outcome; to preserve parse-failure returns you must mark and
preserve the successful result as a primary outcome as well: after calling
runWithBody set a hasPrimaryResult (or reuse hasPrimaryError semantics inverted)
and store result; in the disposeContexts catch, if a primary result exists then
do not let the disposal error overwrite it—return the preserved result (or wrap
the disposal error as suppressed but keep returning the original result) instead
of throwing; update the logic around runWithBody, result, hasPrimaryError, and
disposeContexts to implement this behavior.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 1520ae69-ecd7-4d9e-9e10-4eb907ad7482

📥 Commits

Reviewing files that changed from the base of the PR and between 7970774 and b4ee4c1.

📒 Files selected for processing (2)
  • packages/core/src/facade.test.ts
  • packages/core/src/facade.ts

The extraction left the public API docblock on the private
runWithBody helper while the exported runWith was undocumented.
Move it back and add @throws {SuppressedError} to both runWith
and runWithSync.

#771 (comment)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@dahlia dahlia requested a review from Copilot April 4, 2026 05:05
@dahlia
Copy link
Copy Markdown
Owner Author

dahlia commented Apr 4, 2026

@codex review

@dahlia
Copy link
Copy Markdown
Owner Author

dahlia commented Apr 4, 2026

/gemini review

@chatgpt-codex-connector
Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Another round soon, please!

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 3 out of 3 changed files in this pull request and generated no new comments.

Copy link
Copy Markdown

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request updates runWith and runWithSync to use SuppressedError when both parsing and context disposal fail, ensuring the original parse error is preserved. It introduces a SuppressedError polyfill for compatibility with Node.js versions older than 24 and refactors the core logic into runWithBody and runWithSyncBody helpers. Review feedback identifies a regression in these new helper functions where the removal of optional chaining on the options parameter could cause crashes if the options object is omitted by the user.

Comment thread packages/core/src/facade.ts
Comment thread packages/core/src/facade.ts
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/core/src/facade.ts`:
- Around line 3182-3184: Add a matching `@throws` {SuppressedError} JSDoc entry to
runWithAsync() describing the rejection path where parsing fails and a context
disposal also throws (original parse error available via .suppressed and
disposal error via .error), mirroring the existing `@throws` text used for
runWith()/runWithSync(); also update the other runWithAsync JSDoc occurrence
that exposes the same path so both declarations document this SuppressedError
behavior.
- Around line 69-83: The polyfill uses an unsafe `as unknown as typeof
SuppressedError`; replace that with a local structural constructor type (e.g.
SuppressedErrorConstructor) that models the polyfill shape — a `new(error:
unknown, suppressed: unknown, message?: string)` returning an object with
`.error` and `.suppressed` and extends Error — then type the polyfill factory
and the exported constant `SuppressedErrorCtor` with that structural type
instead of double-casting; update the inner class `SuppressedErrorPolyfill` to
satisfy that type so no `as unknown as` assertions are needed.
🪄 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: Repository UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: e6d64aef-7796-45a8-b5e0-1f40cad1f14a

📥 Commits

Reviewing files that changed from the base of the PR and between b4ee4c1 and 4d8b8f8.

📒 Files selected for processing (1)
  • packages/core/src/facade.ts

Comment thread packages/core/src/facade.ts
Comment thread packages/core/src/facade.ts Outdated
Replace the `as unknown as typeof SuppressedError` double
assertion with a local SuppressedErrorConstructor type that
describes the polyfill's actual shape.  Also add the missing
@throws {SuppressedError} to runWithAsync() JSDoc.

#771 (comment)
#771 (comment)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Comment thread packages/core/src/facade.ts Outdated
@dahlia
Copy link
Copy Markdown
Owner Author

dahlia commented Apr 4, 2026

@codex review

@dahlia
Copy link
Copy Markdown
Owner Author

dahlia commented Apr 4, 2026

/gemini review

@chatgpt-codex-connector
Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Breezy!

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 3 out of 3 changed files in this pull request and generated no new comments.

Copy link
Copy Markdown

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request updates the runWith, runWithSync, and runWithAsync functions to prevent the loss of original parse errors when context disposal also fails. It implements a SuppressedError mechanism, including a polyfill for older runtimes, to wrap both failures according to TC39 conventions. The core logic has been refactored into internal functions to manage disposal sequences more effectively, and new test cases verify the error wrapping behavior across different execution modes. I have no feedback to provide.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/core/src/facade.ts`:
- Around line 3188-3190: Update the JSDoc `@throws` description for
SuppressedError to reflect that any exception thrown by runWithBody() or
runWithSyncBody() (not just parse failures) may be wrapped when a context
disposal also throws; reference SuppressedError and explain that the original
error (whatever its origin: parse errors, duplicate context ID, annotation
collection errors, etc.) is available via `.suppressed` and the disposal error
via `.error`. Apply the same broader wording to the other occurrences noted
(around the documentation blocks for the other two locations).
- Around line 3074-3127: The code currently treats any thrown exception during
the first pass like a parse failure and falls back to runParser(), which causes
the parser to be re-run; change the behavior so thrown exceptions are not
swallowed or retried: in the try/catch around parseAsync/parseSync do not set
firstPassFailed on catch — rethrow the caught error (or remove the catch) so
exceptions bubble out — keep the existing fallback path that calls
injectAnnotationsIntoParser and runParser only for actual Result objects where
success === false (i.e. when firstPassFailed is set due to a non-success Result
from parseAsync/parseSync, not due to an exception). Ensure you update the catch
handling around parseAsync/parseSync and references to
firstPassFailed/firstPassResult so runParser is only invoked for genuine
success:false results.
🪄 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: Repository UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 77056049-3fe6-41d1-9001-056eac9464ee

📥 Commits

Reviewing files that changed from the base of the PR and between 4d8b8f8 and badbb89.

📒 Files selected for processing (1)
  • packages/core/src/facade.ts

Comment thread packages/core/src/facade.ts
Comment thread packages/core/src/facade.ts Outdated
The SuppressedError wraps any exception from the body (not just
parse failures), so say "the runner throws" instead of "parsing
fails".

#771 (comment)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@dahlia
Copy link
Copy Markdown
Owner Author

dahlia commented Apr 4, 2026

@codex review

@dahlia dahlia requested a review from Copilot April 4, 2026 06:02
@dahlia
Copy link
Copy Markdown
Owner Author

dahlia commented Apr 4, 2026

/gemini review

@chatgpt-codex-connector
Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Bravo.

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Copy link
Copy Markdown

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request fixes an issue where runWith and runWithSync would discard the original parse error if a source context's disposal also threw an error. The changes introduce a SuppressedError to wrap both failures, including a polyfill for environments lacking native support. The core logic in facade.ts was refactored to separate the execution body from the disposal phase, ensuring that primary errors are preserved and wrapped if disposal fails. Additionally, comprehensive tests were added to cover various error scenarios, including multiple disposal failures using AggregateError. I have no feedback to provide as there were no review comments.

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 3 out of 3 changed files in this pull request and generated no new comments.

@dahlia dahlia merged commit 5c265bd into main Apr 4, 2026
18 checks passed
@dahlia dahlia deleted the issue-246-suppress-dispose-error branch April 4, 2026 06:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Parse failures in runWith() and runWithSync() are overwritten by context disposal errors

2 participants