Skip to content

[eslint-refiner] no-unsafe-catch-error-property: flow-insensitive guard suppresses unguarded accesses (false negative) #47496

Description

@github-actions

Summary

In no-unsafe-catch-error-property, hasGuard is a single frame-level flag. Any recognized guard (err instanceof Error, getErrorMessage(err), or typeof err === "object" + non-null) sets it for the entire catch frame, and at CatchClause:exit all collected unsafeNodes are skipped. As a result a guard that appears on a different branch than the unsafe access — or textually after it — still suppresses the report, producing false negatives.

Where

  • eslint-factory/src/rules/no-unsafe-catch-error-property.ts:71-109CatchClause:exit returns early / skips every unsafeNode whenever frame.hasGuard is set.
  • Guard setters at :112-121 (getErrorMessage), :125-138 (instanceof / typeof), and :140-162 (&& guard) set top.hasGuard = true without regard to source position or branch relative to the flagged access.

Failure example

catch (err) {
  if (flag) core.info(err.message);        // unguarded; runs when flag is true
  if (err instanceof Error) log(err.stack); // guard on a DIFFERENT branch
}

The first .message access is unguarded at runtime, but the sibling-branch instanceof guard flips hasGuard, so nothing is reported. A guard placed textually after the access has the same suppressing effect.

Proposal

Make a guard cover only the accesses it actually dominates. Preferred: treat a guard as protecting accesses lexically within its guarded branch / consequent, or (minimum bar) require the guard test to precede the access in source order and share an enclosing block. Track guard scope per access rather than one boolean per frame.

Acceptance criteria

  • An unguarded access on a sibling branch is reported even when another branch guards the error.
  • An access textually before the only guard is reported.
  • No new false positives: existing valid patterns (guard-then-access in the same branch; early-return non-null + typeof === "object"; instanceof narrowing; getErrorMessage(err) before access) still pass. Run the full existing no-unsafe-catch-error-property.test.ts suite unchanged.
  • Add tests for: sibling-branch guard, guard-after-access, and a nested-block guard that does dominate (still valid).

Non-duplicate

Distinct from the closed refiner issues (#46992-#46994, #47211-#47212), which target other rules. This is a precision/false-negative fix for the guard model in this rule.

Filed by ESLint Refiner (daily rule-quality refinement).

Generated by 🤖 ESLint Refiner · age00 317.3 AIC · ⌖ 13.1 AIC · ⊞ 4.6K ·

  • expires on Jul 29, 2026, 10:20 PM UTC-08:00

Metadata

Metadata

Labels

cookieIssue Monster Loves Cookies!eslint

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions