{"record":{"id":"1d2fd17fbd8efbe7","repo":"different-ai/openwork","slug":"target-update-version-must-use-the-stable-x-y-z-fo","errorCode":null,"errorMessage":"Target update version must use the stable x.y.z format.","messagePattern":"Target update version must use the stable x\\.y\\.z format\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"apps/desktop/electron/updater.mjs","lineNumber":168,"sourceCode":"  const count = Math.max(parsedLeft.release.length, parsedRight.release.length);\n  for (let index = 0; index < count; index += 1) {\n    const leftPart = parsedLeft.release[index] ?? 0;\n    const rightPart = parsedRight.release[index] ?? 0;\n    if (leftPart !== rightPart) return leftPart < rightPart ? -1 : 1;\n  }\n\n  return comparePrereleaseIdentifiers(parsedLeft.prerelease, parsedRight.prerelease);\n}\n\nfunction isVersionNewer(candidate, current) {\n  const comparison = compareVersions(candidate, current);\n  return comparison === null ? candidate !== current : comparison > 0;\n}\n\nexport function targetedStableUpdaterFeed(currentVersion, targetVersion, allowOlder = false) {\n  const normalizedTarget = normalizeStableTargetVersion(targetVersion);\n  if (!normalizedTarget) {\n    throw new Error(\"Target update version must use the stable x.y.z format.\");\n  }\n  const comparison = compareVersions(normalizedTarget, currentVersion);\n  if (comparison === null) {\n    throw new Error(\"Installed version could not be validated for a targeted update.\");\n  }\n  if (comparison === 0 || (!allowOlder && comparison < 0)) {\n    throw new Error(allowOlder\n      ? \"Recovery target version must differ from the installed version.\"\n      : \"Target update version must be newer than the installed version.\");\n  }\n  return `https://github.com/different-ai/openwork/releases/download/v${normalizedTarget}`;\n}\n\nfunction updaterChannelState(app, channel, targetVersion = null, manifestChannel = \"latest\") {\n  const normalized = normalizeElectronUpdaterChannel(channel, manifestChannel);\n  const currentVersion = resolveAppVersion(app);\n  return {\n    channel: normalized,","sourceCodeStart":150,"sourceCodeEnd":186,"githubUrl":"https://github.com/different-ai/openwork/blob/2b7df46e8ae1517d64c896c7793d2d52ec845669/apps/desktop/electron/updater.mjs#L150-L186","documentation":"Thrown by `targetedStableUpdaterFeed` when the requested target version cannot be normalized to the stable `x.y.z` form via `normalizeStableTargetVersion`. Targeted updates pin the auto-updater to a specific GitHub release tag (`v{x.y.z}`), so prerelease suffixes (e.g. `1.2.3-beta.1`), unstripped `v` prefixes, or malformed strings are rejected.","triggerScenarios":"Calling `targetedStableUpdaterFeed(current, \"1.2.3-beta.1\")`, `targetedStableUpdaterFeed(current, \"abc\")`, `targetedStableUpdaterFeed(current, \"\")`, or any string normalizeStableTargetVersion cannot reduce to three numeric dot-separated parts.","commonSituations":"Pasting a GitHub tag like `v1.2.3` or a beta tag into a targeted-update UI; scripting updates with a version read from a changelog that includes prerelease suffixes; typos in the version string.","solutions":["Pass a plain stable semver string like \"1.2.3\" (strip any leading v and prerelease/build metadata)","Parse out prerelease identifiers before invoking targetedStableUpdaterFeed","Validate the version at the UI/CLI layer with a semver regex before calling"],"exampleFix":"// before\ntargetedStableUpdaterFeed(current, 'v1.2.3-beta.1');\n// after\nconst tag = 'v1.2.3-beta.1'.replace(/^v/, '').split('-')[0];\nif (!/^\\d+\\.\\d+\\.\\d+$/.test(tag)) throw new Error('stable version required');\ntargetedStableUpdaterFeed(current, tag);","handlingStrategy":"validation","validationCode":"const STABLE_SEMVER = /^\\d+\\.\\d+\\.\\d+$/;\nfunction isStableVersion(v) {\n  return typeof v === 'string' && STABLE_SEMVER.test(v.replace(/^v/, ''));\n}","typeGuard":"function isStableSemver(v) {\n  return typeof v === 'string' && /^v?\\d+\\.\\d+\\.\\d+$/.test(v);\n}","tryCatchPattern":"try {\n  const feed = targetedStableUpdaterFeed(current, target);\n} catch (e) {\n  if (e.message.startsWith('Target update version must use the stable')) {\n    showError('Enter a version like 1.2.3 (no prerelease tags)');\n  } else throw e;\n}","preventionTips":["Strip leading 'v' and prerelease suffixes from user-supplied tags","Validate with a semver regex at the UI/CLI boundary","Use a semver library to parse before passing through","Constrain targeted-update pickers to known stable release tags"],"tags":["versioning","updater","validation"],"backgroundTag":"invalid-version-format","analyzedSha":"2b7df46e8ae1517d64c896c7793d2d52ec845669","analyzedAt":"2026-09-01T07:59:23.713Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}