Skip to content

eslint-factory: require-async-entrypoint-catch only tracks FunctionDeclaration, missing async fn-expression/arrow entrypoints an [Content truncated due to length] #43129

Description

@github-actions

Summary

require-async-entrypoint-catch (the newest rule) only detects module-scope async FunctionDeclarations and only flags a bare Identifier() ExpressionStatement. Two common entrypoint shapes silently escape the rule, producing false negatives for exactly the unhandled-rejection class the rule exists to catch.

Gap 1 — async function expressions / arrow functions assigned at module scope

The collector only handles FunctionDeclaration:

FunctionDeclaration(node) {
  if (node.async && node.id?.name && node.parent.type === AST_NODE_TYPES.Program) {
    asyncFunctionNames.add(node.id.name);
  }
},

So these equivalent entrypoints are never tracked and their bare calls are never flagged:

const main = async () => { /* ... */ };
main();                       // FN: unhandled rejection, not flagged

const run = async function () { /* ... */ };
if (require.main === module) run();   // FN

The rule's own test suite documents this boundary (only FunctionDeclaration cases are covered; const main = async () => {} appears only in a valid/await case).

Gap 2 — .then() chained without a .catch()

The call handler bails whenever the callee is not a plain Identifier, so a .then() chain with no rejection handler is treated as "handled":

main().then(() => process.exit(0));   // FN: rejection still unhandled

(A chain that does end in .catch(...) should remain valid, as it is today.)

Grounding / severity

Current live actions/setup/js entrypoints are all either sync function main() (correctly ignored) or async FunctionDeclarations that the rule already catches (e.g. parse_mcp_scripts_logs.cjs:415, parse_token_usage.cjs:238 — true positives). Arrow/expression async entrypoints presently appear only as await-guarded helpers, so this is a preventive robustness/parity refinement: the sibling error-property rules were hardened for computed/aliased forms for the same reason, and detection here should not depend on the author's choice of declaration syntax.

Acceptance criteria

  • Track module-scope async entrypoints declared as const/let/var X = async function () {} and const/let/var X = async () => {} (VariableDeclarator with an async init), in addition to FunctionDeclaration.
  • Flag a bare X() ExpressionStatement for such tracked names, with the existing .catch(...) suggestion fix.
  • Flag X().then(...) ExpressionStatements that do not terminate in a .catch(...); keep chains ending in .catch(...) valid.
  • Add RuleTester cases: valid (.catch present, awaited inside async, sync arrow) and invalid (bare arrow/fn-expr call, .then() without catch) with expected suggestion output.
  • No new false positives against the existing actions/setup/js/**/*.cjs corpus.

See also #42189 / #42915 (branch-order guard FNs in the sibling catch-error-property rules) — same theme of tightening the newest error-handling rules against real-world variance.

Generated by 🤖 ESLint Refiner · 147.1 AIC · ⌖ 12.9 AIC · ⊞ 4.7K ·

  • expires on Jul 9, 2026, 10:27 PM UTC-08:00

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions