Problem
no-empty-catch-block only fires on the CatchClause AST node — i.e. try { } catch { } syntax. It has no coverage for the functionally identical anti-pattern where a Promise chain ends in an empty .catch(() => {}) callback, which silently swallows a rejection with zero diagnostics — exactly the "hidden failures that are hard to diagnose from CI logs" risk this rule exists to catch.
No sibling rule fills the gap either:
require-async-entrypoint-catch (require-async-entrypoint-catch.ts:15-28, chainHasCatch) only checks that a .catch(...) call is present somewhere in the chain — it never inspects whether the callback body actually does anything.
no-unsafe-promise-catch-error-property only fires when the callback does access err.message/.stack/etc. unsafely; a callback that never touches err at all (an empty one) is outside its selector entirely.
Grounded live sites
actions/setup/js/action_setup_otlp.cjs:198: run().catch(() => {});
actions/setup/js/action_conclusion_otlp.cjs:98: run().catch(() => {});
Both are preceded by an explicit comment ("Non-fatal: errors are silently swallowed.") documenting that this is deliberate — OTLP export failures shouldn't fail the job. So today these are legitimate, not bugs. But that is precisely why a new check needs a comment-based exemption identical to no-empty-catch-block's (see the sibling issue on broadening that vocabulary), rather than blanket-flagging every empty .catch() — and until such a check exists at all, an accidentally empty entrypoint .catch(() => {}) introduced elsewhere in the codebase would go completely undetected by any current rule.
Ask
Extend no-empty-catch-block (or add a CallExpression selector alongside its existing CatchClause one) to also flag .catch(callback) calls whose callback has a genuinely empty body, when no comment nearby matches the same intent-signaling vocabulary used for CatchClause. Reuse the same comment-adjacency exemption logic (leading comment inside/immediately above the callback body) so the two documented live sites (action_setup_otlp.cjs:198, action_conclusion_otlp.cjs:98) stay valid once the broadened vocabulary from the sibling issue lands.
Acceptance criteria
Generated by 🤖 ESLint Refiner · agent · 201.6 AIC · ⌖ 4.82 AIC · ⊞ 5.2K · ◷
Problem
no-empty-catch-blockonly fires on theCatchClauseAST node — i.e.try { } catch { }syntax. It has no coverage for the functionally identical anti-pattern where a Promise chain ends in an empty.catch(() => {})callback, which silently swallows a rejection with zero diagnostics — exactly the "hidden failures that are hard to diagnose from CI logs" risk this rule exists to catch.No sibling rule fills the gap either:
require-async-entrypoint-catch(require-async-entrypoint-catch.ts:15-28,chainHasCatch) only checks that a.catch(...)call is present somewhere in the chain — it never inspects whether the callback body actually does anything.no-unsafe-promise-catch-error-propertyonly fires when the callback does accesserr.message/.stack/etc. unsafely; a callback that never toucheserrat all (an empty one) is outside its selector entirely.Grounded live sites
actions/setup/js/action_setup_otlp.cjs:198:run().catch(() => {});actions/setup/js/action_conclusion_otlp.cjs:98:run().catch(() => {});Both are preceded by an explicit comment ("Non-fatal: errors are silently swallowed.") documenting that this is deliberate — OTLP export failures shouldn't fail the job. So today these are legitimate, not bugs. But that is precisely why a new check needs a comment-based exemption identical to
no-empty-catch-block's (see the sibling issue on broadening that vocabulary), rather than blanket-flagging every empty.catch()— and until such a check exists at all, an accidentally empty entrypoint.catch(() => {})introduced elsewhere in the codebase would go completely undetected by any current rule.Ask
Extend
no-empty-catch-block(or add aCallExpressionselector alongside its existingCatchClauseone) to also flag.catch(callback)calls whose callback has a genuinely empty body, when no comment nearby matches the same intent-signaling vocabulary used forCatchClause. Reuse the same comment-adjacency exemption logic (leading comment inside/immediately above the callback body) so the two documented live sites (action_setup_otlp.cjs:198,action_conclusion_otlp.cjs:98) stay valid once the broadened vocabulary from the sibling issue lands.Acceptance criteria
.catch(() => {})/.catch(function () {})with a genuinely empty body and no adjacent explanatory comment.action_setup_otlp.cjs:198andaction_conclusion_otlp.cjs:98do NOT flag, given their existing "Non-fatal: errors are silently swallowed." comment (matched against the broadened vocabulary from the sibling issue)..catch(() => {})is added as aninvalidtest case..catch(err => { ...body... })callbacks remain unaffected (no new false positives on the existing corpus).