Skip to content

eslint-factory: no-core-error-then-process-exit autofix converts a fatal process.exit into a non-equivalent return (grounded FP [Content truncated due to length] #46540

Description

@github-actions

Summary

The no-core-error-then-process-exit suggestion fix replaces core.error(msg); process.exit(nonzero) with core.setFailed(msg); return; (when inside a function). But return and process.exit(nonzero) are not control-flow-equivalent: process.exit aborts the whole process, whereas return only exits the enclosing function and lets callers keep running. When the flagged pair sits inside a helper that returns a value, the autofix silently converts a hard abort into a fall-through that returns undefined.

Grounded evidence

actions/setup/js/convert_gateway_config_shared.cjs (a standalone node step, so it is linted):

function requireEnvVar(name) {
  const value = process.env[name];
  if (!value) {
    core.error(`ERROR: ${name} environment variable is required`);
    process.exit(1);        // flagged pair
  }
  return value;             // contract: returns a string
}

Applying the suggested fix yields core.setFailed(...); return; — the function now returns undefined, and the caller loadGatewayContext (const gatewayOutput = requireEnvVar("MCP_GATEWAY_OUTPUT"), lines 66-72) continues with gatewayOutput === undefined, then calls fs.existsSync(undefined), etc. The same shape recurs at :66-72 (loadGatewayContext) and in convert_gateway_config_copilot.cjs:71-72.

These are node script.cjs steps where process.exit(1) is the correct step-failure signal; there are no Actions post-hooks to bypass.

Why it matters

  • The autofix is unsafe: it turns a clean fatal exit into a continue-with-undefined bug.
  • The diagnostic asserts process.exit(nonzero) "bypasses the proper GitHub Actions failure lifecycle" / skips "cleanup hooks", which does not hold for standalone node scripts (the dominant case here), where a non-zero exit is exactly how the step fails.

Acceptance criteria

  • Suppress the suggestion (report-only, suggest: []) when the enclosing function returns a value or is not the module entrypoint / top-level main, since return cannot reproduce process.exit's process-abort semantics.
  • Add tests: (a) pair inside a value-returning helper -> no autofix; (b) pair at module top level -> existing autofix; (c) pair inside async main() entrypoint -> autofix retained.
  • Re-verify convert_gateway_config_shared.cjs:45-52 and :66-72, and convert_gateway_config_copilot.cjs:71-72: these must not receive a mechanical return autofix, or the fix must preserve abort semantics (e.g. throw).
  • Optionally soften the message to acknowledge that a non-zero process.exit does fail the step in standalone-node contexts, so the rule's value is the annotation/lifecycle nuance rather than "exit is always wrong".

Generated by 🤖 ESLint Refiner · 312.3 AIC · ⌖ 12.9 AIC · ⊞ 4.6K ·

  • expires on Jul 25, 2026, 10:22 PM UTC-08:00

Metadata

Metadata

Labels

cookieIssue Monster Loves Cookies!eslint

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