Skip to content

feat(ts): implement caughtErrorCauses rule#2948

Closed
jcamino wants to merge 1 commit into
flint-fyi:mainfrom
jcamino:revive/1363-caughtErrorCauses
Closed

feat(ts): implement caughtErrorCauses rule#2948
jcamino wants to merge 1 commit into
flint-fyi:mainfrom
jcamino:revive/1363-caughtErrorCauses

Conversation

@jcamino

@jcamino jcamino commented Jun 9, 2026

Copy link
Copy Markdown

PR Checklist

Overview

Draft revival — opening for maintainer review, not asserting merge-readiness.

Revives #1363 (caughtErrorCauses), which stalled on the legacy rule API and on #400. This branch ports it to the current ruleCreator.createRule(language, …) + visitor-services API.

The rule reports throw new <Error>(…) inside a catch block when no cause option is passed, so the original error chain isn't lost.

Porting notes

  • The old preset: "logical" + strictness: "strict" pair maps to presets: ["logicalStrict"] — flag if you'd rather have it in both tiers.
  • hasErrorCause was simplified to the presence check it always effectively was: the original compared the cause initializer against the catch parameter but then returned true unconditionally, so the comparison was dead code. Any cause: property still satisfies the rule (e.g. { cause: wrapError(error) }).
  • The cause detection was then aligned with ESLint preserve-caught-error's semantics, fixing three false positives the original draft had:
    • AggregateError takes its options as the third argumentnew AggregateError([e], "msg", { cause: e }) is now valid (and new AggregateError([e], "msg") is now correctly reported).
    • Shorthand { cause } and string-literal { "cause": e } keys are now recognized.
    • Unknown-shaped options don't report: options passed as a variable, spread arguments at/before the options slot, and object literals containing spreads are treated as unanalyzable, same as ESLint's UNKNOWN_CAUSE bail-out.
  • An undefined guard on the options argument was added for noUncheckedIndexedAccess.
  • Test fixtures reference console, so the test uses domLibRuleTester; fixtures cover all the cases above.

The #400 blocker has lifted — follow-up opportunity

#1363 was marked blocked because verifying that the thrown error's cause is actually the caught error (vs. any value) needs scope analysis (#400). The TypeScript scope manager has since landed (#2828, extended in #2916 with ScopeManager.getScope). This revival preserves the original lenient behavior; tightening it to verify the caught error flows into the cause (directly or wrapped) is now implementable and left as a maintainer-scoped decision — happy to do it in this PR or a follow-up if wanted.

Files

  • packages/ts/src/rules/caughtErrorCauses.ts — the rule
  • packages/ts/src/rules/caughtErrorCauses.test.ts — co-located rule-tester snapshots
  • packages/site/src/content/docs/rules/ts/caughtErrorCauses.mdx — docs
  • packages/ts/src/plugin.ts — alphabetical registration
  • packages/comparisons/src/data.json — entry flipped to status: implemented
  • .changeset/caught-error-causes.md

Local gates

eslint --max-warnings 0 · tsc -b packages/ts · vitest (17/17, rule test) · comparisons/data.test.ts (28/28) · prettier --check — all pass locally.

🤖 Generated with Claude Code

@changeset-bot

changeset-bot Bot commented Jun 9, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 21ed556

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@flint.fyi/ts Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@github-actions

This comment has been minimized.

jcamino added a commit to jcamino/flint that referenced this pull request Jun 9, 2026
…R recipe

Marks flint-fyi#1363 caughtErrorCauses done (draft PR flint-fyi#2948; its flint-fyi#400 blocker closed 2026-06-06). The draft-PR section now leads with the PR-template checklist octoguide enforces (literal 'fixes #' link, [x] on every task, ~~strikethrough~~ N/A form), notes octoguide re-runs on body edits only, documents the gh pr edit GraphQL failure + REST workaround, and de-mangles the placeholder syntax prettier was corrupting.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@netlify

netlify Bot commented Jun 9, 2026

Copy link
Copy Markdown

Deploy Preview for flint-fyi failed.

Name Link
🔨 Latest commit 21ed556
🔍 Latest deploy log https://app.netlify.com/projects/flint-fyi/deploys/6a28b165fef87f0008a54811

Revives flint-fyi#1363, porting it from the legacy typescriptLanguage.createRule API to the current ruleCreator(language, ...)/services API. The old preset/strictness pair (logical + strict) maps to presets: ["logicalStrict"]. hasErrorCause is simplified to the presence check it always effectively was (the original's identifier comparison was dead code), and an undefined guard was added for noUncheckedIndexedAccess.

The blocker recorded on flint-fyi#1363 (scope analysis, flint-fyi#400) has since lifted: the TypeScript scope manager landed in flint-fyi#2828/flint-fyi#2916. Upgrading the rule to verify the cause is actually the caught error is left as a maintainer-scoped follow-up.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@jcamino jcamino force-pushed the revive/1363-caughtErrorCauses branch from f9b612a to 21ed556 Compare June 10, 2026 00:35
jcamino added a commit to jcamino/flint that referenced this pull request Jun 10, 2026
Preset doctrine per Javier: strict tiers are supersets of their base tier — plain-preset rules declare both tiers, strictness:strict stubs declare the Strict tier only. Backlog entries updated with the 2026-06-09 review fixes applied to flint-fyi#2944/flint-fyi#2945/flint-fyi#2946/flint-fyi#2948/flint-fyi#2949.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@kovsu

kovsu commented Jun 10, 2026

Copy link
Copy Markdown
Member

Hi, thanks for your contributions.

To be clear, we don't have any issue with AI-generated code itself. However, as a first-time contributor, you may not yet have enough familiarity with the project's architecture, coding conventions, and established patterns to effectively steer AI-generated suggestions. This can sometimes lead to changes that don't align well with the codebase, creating additional review overhead and maintenance challenges.

For example, the new code we're adding now is specifically designed to avoid these issues(#2395, #2772 and #1404), but the AI-generated code you submitted managed to hit every single pitfall we were trying to avoid.

@JoshuaKGoldberg

Copy link
Copy Markdown
Collaborator

👋 @kovsu, thanks for the thoughtful response - but @jcamino is working with me on this. These PRs won't be moved from draft to review-requested until a human (jcamino) has fixed them up to be ready.

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.

🚀 Feature: Implement caughtErrorCauses rule (TypeScript)

3 participants