docmirror/dev-sidecar · warning

Invalid version string: ${version}

Error message

Invalid version string: ${version}

What it means

parseVersion() parses a version string like 'v1.2.3' or '1.2.3-beta.1' into numeric parts plus a prerelease suffix using a strict regex (^v?digits(\.digits)*[.-]suffix$). If the string does not match — wrong characters, too many dots, empty, or non-version text — this error is thrown. It is thrown inside isNewVersion's try/catch, which converts it to result -999 with a logged error.

Source

Thrown at packages/core/src/utils/util.version.js:4

function parseVersion (version) {
  const matched = version.match(/^v?(\d{1,2}(?:\.\d{1,2})*)[.-]?(.*)$/)
  if (!matched) {
    throw new Error(`Invalid version string: ${version}`)
  }
  const versionInfo = {
    versions: matched[1].split('.'), // 版本号数组
    pre: matched[2], // 预发布版本号
  }

  // 将 versions 中的数字字符串转为数字
  for (let i = 0; i < versionInfo.versions.length; i++) {
    versionInfo.versions[i] = Number.parseInt(versionInfo.versions[i])
  }

  return versionInfo
}

/**
 * 比较版本号
 *
 * @param onlineVersion  线上版本号

View on GitHub (pinned to 7710cd56cc)

Solutions

  1. Validate the version string matches /^v?\d+(\.\d+)*([.-].+)?$/ before parsing
  2. Sanitize what you feed isNewVersion: trim and strip prefixes like 'version ' or build annotations
  3. If using isNewVersion for update checks, handle its -999 return (comparison failed) rather than letting parseVersion throw
  4. Fix the source of the version data (e.g. ensure the remote version endpoint returns a bare semver string)

Example fix

// before
const isNew = version.isNewVersion(fetchVersionBody, '1.2.0') // body may be HTML -> parseVersion throws
// after
function isValidVersion (v) { return typeof v === 'string' && /^v?\d{1,2}(\.\d{1,2})*([.-].+)?$/.test(v.trim()) }
const isNew = isValidVersion(fetchVersionBody) ? version.isNewVersion(fetchVersionBody.trim(), '1.2.0') : -999
Defensive patterns

Strategy: validation

Validate before calling

function isValidVersionString(v) {
  return typeof v === 'string' && /^v?\d{1,2}(?:\.\d{1,2})*[.-]?[^\s]*$/.test(v.trim())
}
// use only when isValidVersionString(remoteVersion) is true

Type guard

function isVersionString(v) { return typeof v === 'string' && /^v?\d{1,2}(?:\.\d{1,2})*([.-].+)?$/.test(v.trim()) }

Try / catch

try {
  const result = version.isNewVersion(online, current)
} catch (e) {
  if (String(e.message).startsWith('Invalid version string')) {
    log.error(`Unparseable version: ${e.message}`)
    return -999 // treat as 'unknown comparison'
  }
  throw e
}

Prevention

When it happens

Trigger: Calling the module's parseVersion (or indirectly isNewVersion) with strings like 'abc', '', '1.2.3.4.5.6...x', 'version 1.2', or a URL/text response mistakenly used as the version; comparing when onlineVersion fetch returned HTML/an error page instead of a version string.

Common situations: Update check against a remote endpoint that returned an error body instead of a version; local package version read from an unexpected source (e.g. malformed package.json); manual version strings with 'v' plus extra text like 'v1.2.3 (build 45)'; empty version variables.

Related errors


AI-assisted analysis of docmirror/dev-sidecar@7710cd56cc (2026-08-31). Data as JSON: /api/errors/6332b1b4a2b607e9. Report an issue: GitHub.