You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Adds a new custom ESLint rule, require-error-code-for-fetch-throw, that flags throw new Error(...) following a bare fetch(...) call when the throw doesn't include a standardized error code (E###, ERR_*, SAFE_OUTPUT_E###) — even in files that have never imported error_codes.cjs.
Evidence
Two existing rules (require-error-code-in-thrown-error and require-error-code-for-github-api-throw) both gate on the file already importing ./error_codes.cjs — they never fire for files that haven't adopted the convention at all. This is a real, recurring gap:
The same adoption gap exists in artifact_client.cjs (31 throws, 5 fetch() calls) and exchange_otlp_workload_identity.cjs (9 throws, 2 fetch() calls) — both call fetch() and throw Error(...) on failure, with no error code anywhere in either file.
Files that already adopted the convention (linear_graphql.cjs, runtime_import.cjs, validate_secrets.cjs) are correctly left untouched by the new rule since they already reference ERR_*/E### codes at their throw sites.
Implementation
New rule: eslint-factory/src/rules/require-error-code-for-fetch-throw.ts
Modeled on the existing require-error-code-for-github-api-throw rule's architecture: map bare fetch(...) call positions per enclosing function, then flag same-function throw new Error(...) statements lacking a code.
Detects only barefetch(...) identifier calls (deliberately excludes member-expression calls like octokit.request(...) or transport.fetch(...), which are covered by the sibling GitHub-API rule or are wrapper abstractions) to avoid overlap/false positives.
Does not gate on error_codes.cjs being imported — that's the entire point of the rule: catching files that haven't adopted the convention yet.
Reuses the shared ERROR_CODE_PATTERN and resolveWriteOnceInitializerChain helpers for consistency with the sibling rule.
Tests: eslint-factory/src/rules/require-error-code-for-fetch-throw.test.ts (6 cases): valid with error-code-suffixed message, valid with inline string-literal code, invalid throw after bare fetch with no code, valid throw with no preceding fetch, valid throw before the fetch call, valid member-expression fetch call not flagged, valid unrelated sibling-function fetch call not flagged.
Registered in eslint-factory/src/index.ts and enabled ("warn") in eslint-factory/eslint.config.cjs for the actions/setup/js lint target.
Documented in eslint-factory/README.md (TOC entry + detail section with flagged/safe examples).
Validation
cd eslint-factory && npm install — succeeds.
npm run build — passes, no type errors.
npm test — 687/687 tests pass (67 files), including the README/rule-registry parity check.
npm run lint:setup-js — exits 0 (all warnings, no errors); the new rule fires 22 times across exactly 3 real files (azure_devops_work_items.cjs, artifact_client.cjs, exchange_otlp_workload_identity.cjs), confirming it's high-signal and not noisy or duplicative of the two existing error-code rules.
Scope
Changes limited to eslint-factory/** (new rule + tests + registration + docs). No changes to actions/setup/js/** source files, Go code, or documentation outside eslint-factory.
Note
Protected files
This patch modifies protected files, which may affect project dependencies, CI/CD pipelines, or agent behaviour.
Protected files
README.md
To route changes like this to a review issue instead of blocking, configure protected-files: fallback-to-issue in your workflow configuration.
Generated by ESLint Miner · copilot · auto · 147.5 AIC · ⌖ 12.7 AIC · ⊞ 6.7K · ◷
Tip
Your pull request is ready to create! 🎉 ✅
Everything is OK—the changes have been pushed to a branch. Please review the protected files, then create the pull request when you are ready.
Create the pull request
The original pull request description is below.
Summary
Adds a new custom ESLint rule,
require-error-code-for-fetch-throw, that flagsthrow new Error(...)following a barefetch(...)call when the throw doesn't include a standardized error code (E###,ERR_*,SAFE_OUTPUT_E###) — even in files that have never importederror_codes.cjs.Evidence
Two existing rules (
require-error-code-in-thrown-errorandrequire-error-code-for-github-api-throw) both gate on the file already importing./error_codes.cjs— they never fire for files that haven't adopted the convention at all. This is a real, recurring gap:actions/setup/js/azure_devops_work_items.cjshas been repeatedly flagged by the Safe Outputs Conformance script's USE-001 check for missing standardized error codes across 5+ separate runs in the last 14 days: [Safe Outputs Conformance] USE-001: azure_devops_work_items.cjs missing standardized error codes #63370, [Safe Outputs Conformance] USE-001: azure_devops_work_items.cjs missing standardized error codes #61738, [Safe Outputs Conformance] USE-001: azure_devops_work_items.cjs missing standardized error codes #61965, [Safe Outputs Conformance] USE-001: azure_devops_work_items.cjs does not use standardized error codes #62136, [Safe Outputs Conformance] USE-001: azure_devops_work_items.cjs missing standardized error codes #62320, plus a fresh instance today ([Safe Outputs Conformance] USE-001: azure_devops_work_items.cjs missing standardized error codes #63790). It still has zero error-code tokens anywhere in the file despite makingfetch()calls and throwing on failure (~55throw new Error(...)sites).artifact_client.cjs(31 throws, 5fetch()calls) andexchange_otlp_workload_identity.cjs(9 throws, 2fetch()calls) — both callfetch()and throwError(...)on failure, with no error code anywhere in either file.linear_graphql.cjs,runtime_import.cjs,validate_secrets.cjs) are correctly left untouched by the new rule since they already referenceERR_*/E###codes at their throw sites.Implementation
eslint-factory/src/rules/require-error-code-for-fetch-throw.tsrequire-error-code-for-github-api-throwrule's architecture: map barefetch(...)call positions per enclosing function, then flag same-functionthrow new Error(...)statements lacking a code.fetch(...)identifier calls (deliberately excludes member-expression calls likeoctokit.request(...)ortransport.fetch(...), which are covered by the sibling GitHub-API rule or are wrapper abstractions) to avoid overlap/false positives.error_codes.cjsbeing imported — that's the entire point of the rule: catching files that haven't adopted the convention yet.ERROR_CODE_PATTERNandresolveWriteOnceInitializerChainhelpers for consistency with the sibling rule.eslint-factory/src/rules/require-error-code-for-fetch-throw.test.ts(6 cases): valid with error-code-suffixed message, valid with inline string-literal code, invalid throw after bare fetch with no code, valid throw with no preceding fetch, valid throw before the fetch call, valid member-expressionfetchcall not flagged, valid unrelated sibling-function fetch call not flagged.eslint-factory/src/index.tsand enabled ("warn") ineslint-factory/eslint.config.cjsfor theactions/setup/jslint target.eslint-factory/README.md(TOC entry + detail section with flagged/safe examples).Validation
cd eslint-factory && npm install— succeeds.npm run build— passes, no type errors.npm test— 687/687 tests pass (67 files), including the README/rule-registry parity check.npm run lint:setup-js— exits 0 (all warnings, no errors); the new rule fires 22 times across exactly 3 real files (azure_devops_work_items.cjs,artifact_client.cjs,exchange_otlp_workload_identity.cjs), confirming it's high-signal and not noisy or duplicative of the two existing error-code rules.Scope
Changes limited to
eslint-factory/**(new rule + tests + registration + docs). No changes toactions/setup/js/**source files, Go code, or documentation outsideeslint-factory.Note
Protected files
This patch modifies protected files, which may affect project dependencies, CI/CD pipelines, or agent behaviour.
Protected files
README.mdTo route changes like this to a review issue instead of blocking, configure
protected-files: fallback-to-issuein your workflow configuration.