{"record":{"id":"202cd22a2cf18e48","repo":"paperclipai/paperclip","slug":"downgrade-cancelled-re-run-with-yes-to-confirm","errorCode":null,"errorMessage":"Downgrade cancelled. Re-run with --yes to confirm explicitly.","messagePattern":"Downgrade cancelled\\. Re-run with --yes to confirm explicitly\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"info","filePath":"cli/src/commands/update.ts","lineNumber":221,"sourceCode":"    try {\n      restarted = await (overrides.restartActiveService ?? restartActiveManagedService)(installed.version);\n    } catch (error) {\n      return rollbackAfterServiceValidationFailure(\n        paths,\n        overrides.restartActiveService ?? restartActiveManagedService,\n        error,\n        \"Updated git payload\",\n      );\n    }\n    emit(options, { mode, source: \"git\", changed: true, currentSha: manifest.sha, targetSha, reused: installed.reused, restarted }, pc.yellow(`Updated unreleased git payload ${manifest.sha.slice(0, 12)} → ${targetSha.slice(0, 12)} from ${manifest.repo}@${manifest.ref}${restarted ? \" and restarted the active service\" : \"\"}.`));\n    return;\n  }\n  const targetVersion = await resolvePublishedVersion(request.spec, runCommand);\n  const currentVersion = manifest?.version ?? (mode === \"global-npm\" ? packageVersion : undefined);\n  const comparison = currentVersion ? compareVersions(targetVersion, currentVersion) : 1;\n  if (options.check) { emit(options, { mode, currentVersion: currentVersion ?? null, targetVersion, updateAvailable: comparison > 0, downgrade: comparison < 0, channel: request.channel }, comparison > 0 ? `Update available: ${targetVersion}` : comparison < 0 ? `Target ${targetVersion} is older than ${currentVersion}.` : `paperclipai ${targetVersion} is current.`); if (comparison > 0) process.exitCode = 10; return; }\n  if (mode === \"global-npm\") {\n    if (comparison < 0 && options.yes !== true) { const confirmed = await (overrides.confirm ?? defaultConfirm)(`Downgrade paperclipai from ${currentVersion} to ${targetVersion}?`); if (!confirmed) throw new Error(\"Downgrade cancelled. Re-run with --yes to confirm explicitly.\"); }\n    const args = [\"install\", \"-g\", `paperclipai@${targetVersion}`, `--registry=${PUBLIC_NPM_REGISTRY}`, `--@paperclipai:registry=${PUBLIC_NPM_REGISTRY}`]; console.log(`Running: npm ${args.join(\" \")}`);\n    if (!options.dryRun) {\n      const npmConfigDir = fs.mkdtempSync(path.join(os.tmpdir(), \"paperclip-npm-\"));\n      const npmUserConfigPath = path.join(npmConfigDir, \"npmrc\");\n      try {\n        fs.writeFileSync(npmUserConfigPath, `registry=${PUBLIC_NPM_REGISTRY}\\n@paperclipai:registry=${PUBLIC_NPM_REGISTRY}\\n`, { mode: 0o600 });\n        await runCommand(\"npm\", args, {\n          env: {\n            ...process.env,\n            npm_config_registry: PUBLIC_NPM_REGISTRY,\n            NPM_CONFIG_REGISTRY: PUBLIC_NPM_REGISTRY,\n            npm_config_userconfig: npmUserConfigPath,\n            NPM_CONFIG_USERCONFIG: npmUserConfigPath,\n          },\n          maxBuffer: 16 * 1024 * 1024,\n        });\n      } finally {\n        fs.rmSync(npmConfigDir, { recursive: true, force: true });","sourceCodeStart":203,"sourceCodeEnd":239,"githubUrl":"https://github.com/paperclipai/paperclip/blob/67001ec6eb96ae601aa27bc91d9b2415d665334a/cli/src/commands/update.ts#L203-L239","documentation":"Thrown by updateCommand on the global-npm path when the resolved target version is older than the currently installed version (compareVersions returns negative), options.yes is not true, and the downgrade confirmation prompt returns false. Downgrades are gated because they can roll back migrations/features, so explicit consent is required.","triggerScenarios":"Global-npm install mode, `paperclipai update --version <older>` (or a canary/latest resolution that points backward), user declines the 'Downgrade paperclipai from X to Y?' prompt. Also auto-thrown in non-TTY contexts where defaultConfirm returns false unless --yes is passed.","commonSituations":"Pinning to an older release to dodge a regression, run from a pipe/CI without --yes. Typing a wrong (older) version number. Canary channel resolving to an older build.","solutions":["Confirm explicitly: `paperclipai update --version <older> --yes`.","Accept the prompt interactively (y/Enter) when in a TTY.","Double-check the target version is what you intend if the downgrade is unintentional."],"exampleFix":"# before\npaperclipai update --version 1.0.0\n# after\npaperclipai update --version 1.0.0 --yes","handlingStrategy":"validation","validationCode":"// Decide downgrade consent up front for global-npm\nimport { compareVersions } from '../commands/update.js';\nfunction shouldAutoConfirmDowngrade(current: string, target: string, yes?: boolean): boolean {\n  return compareVersions(target, current) < 0 ? Boolean(yes) : true;\n}\n// options.yes = shouldAutoConfirmDowngrade(currentVersion, targetVersion, options.yes);","typeGuard":null,"tryCatchPattern":"try {\n  await updateCommand(options);\n} catch (error) {\n  if (error instanceof Error && error.message === 'Downgrade cancelled. Re-run with --yes to confirm explicitly.') {\n    // respect the user's cancellation; only retry once they pass --yes\n    throw error;\n  } else throw error;\n}","preventionTips":["Pass --yes in scripts whenever you intentionally downgrade.","Verify the target version is older than current before scripting a downgrade.","In TTY sessions, answer the prompt affirmatively rather than re-running."],"tags":["downgrade","npm","confirmation","update"],"backgroundTag":null,"analyzedSha":"67001ec6eb96ae601aa27bc91d9b2415d665334a","analyzedAt":"2026-08-12T12:05:45.408Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}