nodejs/node · error · Error

Tag name must not be a valid SemVer range: ${defaultTag.trim

Error message

Tag name must not be a valid SemVer range: ${defaultTag.trim()}

What it means

Thrown by the `npm publish` command when the configured default tag (from `npm config get tag`, typically 'latest') is itself a valid SemVer range. npm dist-tags use arbitrary string names (like 'latest', 'beta', 'next'), and if the tag name looks like a SemVer range (e.g. '1.0.0', '>=1.0.0', '1.x'), it would be ambiguous with version ranges in resolution and is explicitly rejected.

Source

Thrown at deps/npm/lib/commands/publish.js:90

  }

  get #command () {
    return this.isStage ? 'stage' : 'publish'
  }

  async #publish (args, { workspace } = {}) {
    log.verbose(this.#command, replaceInfo(args))

    const unicode = this.npm.config.get('unicode')
    const dryRun = this.npm.config.get('dry-run')
    const json = this.npm.config.get('json')
    const defaultTag = this.npm.config.get('tag')
    const ignoreScripts = this.npm.config.get('ignore-scripts')
    const scriptShell = this.npm.config.get('script-shell') || undefined
    const { silent } = this.npm

    if (semver.validRange(defaultTag)) {
      throw new Error('Tag name must not be a valid SemVer range: ' + defaultTag.trim())
    }

    const opts = { ...this.npm.flatOptions, progress: false }

    // you can publish name@version, ./foo.tgz, etc even though the default is the 'file:.' cwd.
    const spec = npa(args[0])
    let manifest = await this.#getManifest(spec, opts)

    // only run scripts for directory type publishes
    if (spec.type === 'directory' && !ignoreScripts) {
      await runScript({
        event: 'prepublishOnly',
        path: spec.fetchSpec,
        stdio: 'inherit',
        pkg: manifest,
        scriptShell,
      })
    }

View on GitHub (pinned to 1b2de5e052)

Solutions

  1. Use a named tag that is not a SemVer range: 'latest', 'beta', 'next', 'alpha'
  2. Check your .npmrc for a `tag=` line and ensure it is a word, not a version
  3. If using --tag in a script, pass a dist-tag name, not a version number
  4. Reset to default: `npm config delete tag`

Example fix

// before — in .npmrc or CLI
tag=1.0.0
// or: npm publish --tag 2.1.0

// after — use a named dist-tag
tag=latest
// or: npm publish --tag beta
Defensive patterns

Strategy: validation

Validate before calling

const semver = require('semver')
function isValidDistTag(tag) {
  return typeof tag === 'string' && tag.length > 0 && !semver.validRange(tag)
}
// Before publishing:
const tag = npm.config.get('tag')
if (!isValidDistTag(tag)) {
  throw new Error(`Tag "${tag}" is a valid SemVer range — use a named tag like 'latest', 'beta', 'next'`)
}

Type guard

function isNonSemverTag(tag) {
  const semver = require('semver')
  return typeof tag === 'string' && tag.length > 0 && !semver.validRange(tag)
}

Try / catch

try {
  await exec([pkgSpec])
} catch (e) {
  if (e.message.includes('Tag name must not be a valid SemVer')) {
    console.error('Set a named dist-tag: npm publish --tag latest')
  }
  throw e
}

Prevention

When it happens

Trigger: The `defaultTag` variable is read from `this.npm.config.get('tag')`. If someone sets `tag=1.0.0` or `tag=>=1.0.0` in .npmrc or via `--tag`, `semver.validRange(defaultTag)` returns truthy and the error fires.

Common situations: Mistakenly setting `tag` to a version string in .npmrc instead of a named tag. Confusing the `--tag` flag (dist-tag name) with a version. Copy-publishing scripts that pass a version where a tag name belongs. CI scripts that dynamically set `--tag` to a version variable.

Related errors


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