{"record":{"id":"1a7237a5c61c593b","repo":"different-ai/openwork","slug":"recovery-target-version-must-differ-from-the-insta","errorCode":null,"errorMessage":"Recovery target version must differ from the installed version.","messagePattern":"Recovery target version must differ from the installed version\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"apps/desktop/electron/updater.mjs","lineNumber":175,"sourceCode":"  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,\n    feedUrl: targetVersion\n      ? targetedStableUpdaterFeed(currentVersion, targetVersion)\n      : electronUpdaterFeedUrl(normalized, manifestChannel),\n    currentVersion,\n  };\n}\n","sourceCodeStart":157,"sourceCodeEnd":193,"githubUrl":"https://github.com/different-ai/openwork/blob/2b7df46e8ae1517d64c896c7793d2d52ec845669/apps/desktop/electron/updater.mjs#L157-L193","documentation":"Thrown by `targetedStableUpdaterFeed` when recovery mode (`allowOlder = true`) is requested but the target version compares equal to the installed version (`comparison === 0`). Recovery updates exist to move the install to a different (possibly older) known-good release; targeting the identical version is a no-op and is rejected explicitly (non-recovery mode emits the sibling message about needing a newer version).","triggerScenarios":"Calling `targetedStableUpdaterFeed(current, current, true)` or otherwise passing a target equal to the running version with allowOlder set.","commonSituations":"A recovery UI defaulting the version field to the currently installed version; automation computing the target from the installed version; stale state after a successful update where the app already runs the recovery target.","solutions":["Pass a recovery target different from the installed version (the known-good older release you intend)","Check the installed version first and skip the update if it already matches the target","Fix automation that copies currentVersion into the target field"],"exampleFix":"// before\ntargetedStableUpdaterFeed(installed, recoveryTarget, true); // same version\n// after\nif (recoveryTarget === installed) return; // already on recovery version\ntargetedStableUpdaterFeed(installed, recoveryTarget, true);","handlingStrategy":"validation","validationCode":"function recoveryTargetDiffers(current, target, allowOlder) {\n  return !allowOlder || target !== current;\n}","typeGuard":null,"tryCatchPattern":"try {\n  const feed = targetedStableUpdaterFeed(current, target, true);\n} catch (e) {\n  if (e.message.startsWith('Recovery target version must differ')) {\n    showError('Already running the recovery version — nothing to do');\n  } else throw e;\n}","preventionTips":["Compare target to the installed version before offering recovery","Never default the recovery field to the current version","After a successful recovery, clear stale recovery-target state","Treat 'already on target' as a no-op success rather than an error condition"],"tags":["versioning","updater","recovery"],"backgroundTag":"target-version-equals-installed","analyzedSha":"2b7df46e8ae1517d64c896c7793d2d52ec845669","analyzedAt":"2026-09-01T07:59:23.713Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}