different-ai/openwork · error

Target update version must use the stable x.y.z format.

Error message

Target update version must use the stable x.y.z format.

What it means

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.

Source

Thrown at apps/desktop/electron/updater.mjs:168

  const count = Math.max(parsedLeft.release.length, parsedRight.release.length);
  for (let index = 0; index < count; index += 1) {
    const leftPart = parsedLeft.release[index] ?? 0;
    const rightPart = parsedRight.release[index] ?? 0;
    if (leftPart !== rightPart) return leftPart < rightPart ? -1 : 1;
  }

  return comparePrereleaseIdentifiers(parsedLeft.prerelease, parsedRight.prerelease);
}

function isVersionNewer(candidate, current) {
  const comparison = compareVersions(candidate, current);
  return comparison === null ? candidate !== current : comparison > 0;
}

export function targetedStableUpdaterFeed(currentVersion, targetVersion, allowOlder = false) {
  const normalizedTarget = normalizeStableTargetVersion(targetVersion);
  if (!normalizedTarget) {
    throw new Error("Target update version must use the stable x.y.z format.");
  }
  const comparison = compareVersions(normalizedTarget, currentVersion);
  if (comparison === null) {
    throw new Error("Installed version could not be validated for a targeted update.");
  }
  if (comparison === 0 || (!allowOlder && comparison < 0)) {
    throw new Error(allowOlder
      ? "Recovery target version must differ from the installed version."
      : "Target update version must be newer than the installed version.");
  }
  return `https://github.com/different-ai/openwork/releases/download/v${normalizedTarget}`;
}

function updaterChannelState(app, channel, targetVersion = null, manifestChannel = "latest") {
  const normalized = normalizeElectronUpdaterChannel(channel, manifestChannel);
  const currentVersion = resolveAppVersion(app);
  return {
    channel: normalized,

View on GitHub (pinned to 2b7df46e8a)

Solutions

  1. Pass a plain stable semver string like "1.2.3" (strip any leading v and prerelease/build metadata)
  2. Parse out prerelease identifiers before invoking targetedStableUpdaterFeed
  3. Validate the version at the UI/CLI layer with a semver regex before calling

Example fix

// before
targetedStableUpdaterFeed(current, 'v1.2.3-beta.1');
// after
const tag = 'v1.2.3-beta.1'.replace(/^v/, '').split('-')[0];
if (!/^\d+\.\d+\.\d+$/.test(tag)) throw new Error('stable version required');
targetedStableUpdaterFeed(current, tag);
Defensive patterns

Strategy: validation

Validate before calling

const STABLE_SEMVER = /^\d+\.\d+\.\d+$/;
function isStableVersion(v) {
  return typeof v === 'string' && STABLE_SEMVER.test(v.replace(/^v/, ''));
}

Type guard

function isStableSemver(v) {
  return typeof v === 'string' && /^v?\d+\.\d+\.\d+$/.test(v);
}

Try / catch

try {
  const feed = targetedStableUpdaterFeed(current, target);
} catch (e) {
  if (e.message.startsWith('Target update version must use the stable')) {
    showError('Enter a version like 1.2.3 (no prerelease tags)');
  } else throw e;
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of different-ai/openwork@2b7df46e8a (2026-09-01). Data as JSON: /api/errors/1d2fd17fbd8efbe7. Report an issue: GitHub.