nodejs/node · error · Error

Token ID "${id}" was ambiguous, a new token may have been cr

Error message

Token ID "${id}" was ambiguous, a new token may have been created since you last ran `npm token list`.

What it means

Thrown by `npm token rm` when the given id is a prefix that matches more than one token's `key`. npm refuses to guess which token to delete, and hints that a newer token may have shifted the matching set since the last `npm token list`.

Source

Thrown at deps/npm/lib/commands/token.js:126

    }
  }

  async rm (args) {
    if (args.length === 0) {
      throw this.usageError('`<tokenKey>` argument is required.')
    }

    const json = this.npm.config.get('json')
    const parseable = this.npm.config.get('parseable')
    const toRemove = []
    log.info('token', `removing ${toRemove.length} tokens`)
    const tokens = await paginate('/-/npm/v1/tokens', this.npm.flatOptions)
    for (const id of args) {
      const matches = tokens.filter(token => token.key.indexOf(id) === 0)
      if (matches.length === 1) {
        toRemove.push(matches[0].key)
      } else if (matches.length > 1) {
        throw new Error(
          `Token ID "${id}" was ambiguous, a new token may have been created since you last ran \`npm token list\`.`
        )
      } else {
        const tokenMatches = tokens.some(t => id.indexOf(t.token) === 0)
        if (!tokenMatches) {
          throw new Error(`Unknown token id or value "${id}".`)
        }

        toRemove.push(id)
      }
    }
    for (const tokenKey of toRemove) {
      await otplease(this.npm, this.npm.flatOptions, opts =>
        fetch(`/-/npm/v1/tokens/token/${tokenKey}`, {
          ...opts,
          method: 'DELETE',
          ignoreBody: true,
        })

View on GitHub (pinned to 1b2de5e052)

Solutions

  1. Run `npm token list` to get current full token ids, then pass a longer/unique prefix or the full id.
  2. Pass the complete token key to disambiguate.
  3. If prefix collisions are common, revoke tokens individually with the full id.

Example fix

// before
npm token rm abc123   // matches 2 tokens
// after
npm token rm abc123def456-full-key
Defensive patterns

Strategy: validation

Validate before calling

function resolveTokenId(id, tokens) {
  const matches = tokens.filter(t => t.key.indexOf(id) === 0)
  if (matches.length > 1) {
    throw new Error(`Token id "${id}" is ambiguous (${matches.length} matches). Use the full key.`)
  }
  return matches[0]?.key ?? null
}

Prevention

When it happens

Trigger: In the revoke loop, `tokens.filter(t => t.key.indexOf(id) === 0).length > 1` — the id is a prefix of two or more token keys.

Common situations: Using a short id prefix that several tokens share; revoking after new tokens were created (CI rotations) that share the same prefix; copying only the first few characters of a token id.

Related errors


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