nodejs/node · error · Error

Invalid URL: ${url}

Error message

Invalid URL: ${url}

What it means

Thrown by assertValidUrl in open-url.js when the URL either fails to parse via the URL constructor or parses but has a protocol other than `http:` or `https:`. The helper is used by openUrl (unless isFile is true, as for help pages) and by openUrlPrompt before showing a login URL. It guards against `file:`, `javascript:`, or malformed strings being handed to the browser opener.

Source

Thrown at deps/npm/lib/utils/open-url.js:13

const { open } = require('@npmcli/promise-spawn')
const { output, input, META } = require('proc-log')
const { URL } = require('node:url')
const readline = require('node:readline/promises')
const { once } = require('node:events')

const assertValidUrl = (url) => {
  try {
    if (!/^https?:$/.test(new URL(url).protocol)) {
      throw new Error()
    }
  } catch {
    throw new Error('Invalid URL: ' + url)
  }
}

const outputMsg = (json, title, url) => {
  if (json) {
    output.buffer({ title, url })
  } else {
    // These urls are sometimes specifically login urls so we have to turn off redaction to standard output
    output.standard(`${title}:\n${url}`, { [META]: true, redact: false })
  }
}

// attempt to open URL in web-browser, print address otherwise:
const openUrl = async (npm, url, title, isFile) => {
  url = encodeURI(url)
  const browser = npm.config.get('browser')
  const json = npm.config.get('json')

View on GitHub (pinned to 1b2de5e052)

Solutions

  1. Ensure the relevant metadata/config (homepage, repository.url, docs) is a fully-qualified `https://` URL.
  2. If hitting this during `npm login`, verify the registry's web base URL is reachable and absolute.
  3. For local help/file URLs, note the openUrl `isFile` path skips this check; use the help flow rather than a custom URL.

Example fix

// before
// package.json: "homepage": "git@github.com:owner/repo"
npm repo
// after
// package.json: "homepage": "https://github.com/owner/repo"
npm repo
Defensive patterns

Strategy: validation

Validate before calling

const assertHttpUrl = (url) => {
  let u
  try { u = new URL(url) } catch { throw new Error(`Invalid URL: ${url}`) }
  if (!/^https?:$/.test(u.protocol)) throw new Error(`Invalid URL: ${url}`)
}

Type guard

const isHttpUrl = (v) => {
  try { return /^https?:$/.test(new URL(v).protocol) } catch { return false }
}

Try / catch

try {
  await openUrl(npm, url, title, isFile)
} catch (err) {
  if (/^Invalid URL:/i.test(err.message)) {
    // log the offending URL source field (homepage/repository) for the user to fix
  } else { throw err }
}

Prevention

When it happens

Trigger: An npm command (e.g. login, docs, repo, author) computes a URL that is non-HTTP, or a custom config value (homepage, repository, docs) resolves to something unparsable or to a `file:`/`git:` URL. Also if a registry or auth opener returns a malformed URL.

Common situations: package.json `homepage` set to a `git@host:` SSH string or a relative path; a plugin/proxy that returns a non-absolute login URL; typos like 'htp://'; an internal registry whose web UI config field is empty.

Related errors


AI-assisted analysis of nodejs/node@1b2de5e052 (2026-08-13). Data as JSON: /api/errors/4d873baa0873133d. Report an issue: GitHub.