nodejs/node · info · Error

canceled

Error message

canceled

What it means

Thrown by npm's openUrlPrompt when a SIGINT (Ctrl+C) is received on the readline interface while waiting for the user to press ENTER to open a URL in the browser. It represents an intentional user cancellation of a browser-based auth/OTP flow (e.g. npm login / adduser / publish with web auth), not a malfunction. The error is created as a plain Error (not AbortError), so the surrounding catch (which only suppresses AbortError) re-throws it.

Source

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

  assertValidUrl(url)
  outputMsg(json, title, url)

  if (browser === false || !process.stdin.isTTY || !process.stdout.isTTY) {
    return
  }

  const rl = readline.createInterface({
    input: process.stdin,
    output: process.stdout,
  })

  try {
    await input.read(() => Promise.race([
      rl.question(prompt, { signal }),
      once(rl, 'error'),
      once(rl, 'SIGINT').then(() => {
        throw new Error('canceled')
      }),
    ]))
    rl.close()
    await openUrl(npm, url, 'Browser unavailable. Please open the URL manually')
  } catch (err) {
    rl.close()
    if (err.name !== 'AbortError') {
      throw err
    }
  }
}

// Rearrange arguments and return a function that takes the two arguments returned from the npm-profile methods that take an opener
const createOpener = (npm, title, prompt = 'Press ENTER to open in the browser...') =>
  (url, opts) => openUrlPrompt(npm, url, title, prompt, opts)

module.exports = {
  openUrl,

View on GitHub (pinned to 1b2de5e052)

Solutions

  1. Treat it as expected: this is the user cancelling, so simply re-run the command when ready or use a non-interactive auth method (e.g. npm config set //registry/:_authToken).
  2. If running in CI, ensure stdin is not a TTY (process.stdin.isTTY === false) so the prompt is skipped entirely, or pre-set credentials via NPM_TOKEN.
  3. If forwarding SIGINT unintentionally, run the npm command in a process group that does not relay Ctrl+C to the child.
  4. To suppress in tooling, wrap the npm invocation and treat exit code / stderr containing 'canceled' as a benign cancellation.

Example fix

// before: interactive prompt blocks CI, Ctrl+C surfaces as fatal 'canceled'
// after: skip the prompt by providing a token non-interactively
npm config set //registry.npmjs.org/:_authToken "$NPM_TOKEN"
npm publish --access public
Defensive patterns

Strategy: try-catch

Try / catch

// openUrlPrompt is internal to npm; guard at the process level when invoking npm.
const { spawnSync } = require('node:child_process')
const res = spawnSync('npm', ['login'], { stdio: 'inherit' })
if (res.status !== 0 && /canceled/.test(String(res.stderr))) {
  console.log('user cancelled the browser login flow')
}

Prevention

When it happens

Trigger: Running a command that calls createOpener/openUrlPrompt (npm login, npm adduser, npm publish with provenance/OTP web flow, npm token create), seeing the 'Press ENTER to open in the browser...' prompt, and pressing Ctrl+C (or a parent process forwarding SIGINT) before pressing ENTER.

Common situations: User changes their mind mid-login; a wrapper/CI process forwards Ctrl+C; an interactive prompt is mistakenly reached in a pseudo-TTY where Ctrl+C is sent automatically; the browser failed to open and the user aborts.

Related errors


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