Skip to content

eslint-factory: require-new-url-try-catch — false positives for provably non-throwing new URL(...) arguments #46151

Description

@github-actions

Rule

require-new-url-try-catch

Summary

isDynamicArg treats every non-Literal, non-empty-TemplateLiteral first argument as runtime-dynamic and therefore parse-risky. Two argument shapes that provably never throw are still flagged, producing false positives:

  1. Compile-time constant string concatenationnew URL("(example.com/redacted)" + "/path"). The argument is a BinaryExpression of two string literals; it evaluates to a constant valid URL and cannot throw.
  2. import.meta.url as the sole / first argumentnew URL(import.meta.url). import.meta.url is always a valid absolute URL in ES modules, so the constructor never throws. The rule already whitelists import.meta.url via isKnownSafeBase, but only for the second (base) argument; the same value in first-argument position is flagged.

Reproduction (currently flagged, should be valid)

// (1) constant concatenation — never throws
new URL("(example.com/redacted)" + "/repos");
// (2) import.meta.url as sole argument — never throws (ES module)
const u = new URL(import.meta.url);

Consistency rationale

The sibling rule no-github-request-interpolated-route explicitly accepts compile-time constant concatenations ("GET /repos" + "/{owner}/{repo}") as safe (see eslint-factory/README.md). require-new-url-try-catch should apply the same "provably-constant is safe" principle, and should honor its own isKnownSafeBase whitelist symmetrically in first-argument position.

Grounding / severity

Logic-derived precision refinement; low current frequency in actions/setup/js (the live new URL(...) sites use genuinely dynamic arguments — e.g. generate_history_link.cjs:61, awf_reflect.cjs:140 (already wrapped), sanitize_content_core.cjs:85 — and are handled correctly). Filed to prevent false positives that would push authors to wrap statements that cannot fail.

Acceptance criteria

  • Treat a BinaryExpression whose operands are (recursively) string literals / expression-less template literals as a non-dynamic, non-throwing argument.
  • Reuse isKnownSafeBase for the first argument as well, so new URL(import.meta.url) is not flagged.
  • Add valid-case tests for both forms above; keep existing invalid cases (new URL(host + "/x") where host is a variable must still flag) to confirm the fix only exempts provably-constant / known-safe values.
  • Leave genuinely dynamic single-variable and template-with-expression arguments in scope (no change).

Generated by 🤖 ESLint Refiner · 429.1 AIC · ⌖ 13.4 AIC · ⊞ 4.6K ·

  • expires on Jul 23, 2026, 10:20 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