Skip to content

eslint-factory: bring no-unsafe-promise-catch-error-property to parity with its sibling (computed access + non-message suggestio [Content truncated due to length] #42914

Description

@github-actions

Summary

no-unsafe-promise-catch-error-property was created as a near-copy of no-unsafe-catch-error-property but did not receive two refinements the sibling has since gained (tracked by #42190). This is refinement drift: two rules with the same intent now diverge in coverage and diagnostic quality.

Gap 1 — computed string-literal access is not detected

The promise rule only inspects !node.computed member access, so err["message"] inside a .catch() callback is silently ignored. The current test suite even codifies this as valid:

// no-unsafe-promise-catch-error-property.test.ts ("valid: computed property access ...")
valid: [`promise.catch(err => { console.log(err["message"]); });`, ...]

The sibling no-unsafe-catch-error-property already flags computed string-literal access (err["message"], err["status"], ...) while intentionally leaving dynamic err[prop] out of scope — see its MemberExpression handler.

Gap 2 — no suggestion for non-message properties

In the promise rule, exitFunction attaches a getErrorMessage() suggestion only when prop === "message" and undefined otherwise. So err.stack, err.code, err.status, err.cause, err.name are flagged with no actionable fix. The sibling offers a wrapWithInstanceof suggestion for exactly these props:

// no-unsafe-catch-error-property.ts
wrapWithInstanceof: "Wrap with '({{errorVar}} instanceof Error ? {{errorVar}}.{{prop}} : undefined)' ..."

Suggested refinement

Port both behaviors from no-unsafe-catch-error-property to no-unsafe-promise-catch-error-property:

  1. Detect computed string-literal access err["<prop>"] for the same UNSAFE_PROPERTIES set.
  2. Add a wrapWithInstanceof suggestion for non-message props.

The two rules already share UNSAFE_PROPERTIES, isTypeofObjectCheck, and isNonNullGuardCheck verbatim — extracting the shared reporting logic would also prevent future drift.

Acceptance criteria

  • promise.catch(err => log(err["message"])) is flagged (update the now-incorrect "valid" test to "invalid").
  • err.stack / err.code / err.status / err.cause / err.name in a .catch() callback each carry a wrapWithInstanceof suggestion.
  • Dynamic err[prop] (non-literal) remains out of scope (no diagnostic), matching the sibling.
  • Test coverage added for both behaviors.

Filed by ESLint Refiner. Sibling reference: #42190. Verified against the two rule sources at time of writing.

Generated by 🤖 ESLint Refiner · 253.6 AIC · ⌖ 10.2 AIC · ⊞ 4.7K ·

  • expires on Jul 8, 2026, 10:35 PM UTC-08:00

Metadata

Metadata

Type

No type

Fields

No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions