{"record":{"id":"0314126c665aa35e","repo":"paperclipai/paperclip","slug":"payloadlabel-failed-service-validation-and-was","errorCode":null,"errorMessage":"${payloadLabel} failed service validation and was rolled back to ${rolledBack.version}, but the rolled-back service also failed to restart.","messagePattern":"(.+?) failed service validation and was rolled back to (.+?), but the rolled-back service also failed to restart\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"cli/src/commands/update.ts","lineNumber":159,"sourceCode":"\nasync function defaultConfirm(message: string): Promise<boolean> {\n  if (!process.stdin.isTTY || !process.stdout.isTTY) return false;\n  const answer = await p.confirm({ message, initialValue: false });\n  return !p.isCancel(answer) && answer === true;\n}\nfunction emit(options: UpdateOptions, value: Record<string, unknown>, message: string): void { if (options.json) console.log(JSON.stringify(value, null, 2)); else console.log(message); }\n\nasync function rollbackAfterServiceValidationFailure(\n  paths: InstallStorePaths,\n  restartActiveService: (expectedVersion: string) => Promise<boolean>,\n  validationError: unknown,\n  payloadLabel: string,\n): Promise<never> {\n  const rolledBack = await withInstallStoreLock(async () => rollbackManagedInstall(paths), paths);\n  try {\n    await restartActiveService(rolledBack.version);\n  } catch (restartError) {\n    throw new Error(\n      `${payloadLabel} failed service validation and was rolled back to ${rolledBack.version}, but the rolled-back service also failed to restart.`,\n      { cause: new AggregateError([validationError, restartError]) },\n    );\n  }\n  throw new Error(`${payloadLabel} failed service validation and was rolled back to ${rolledBack.version}.`, { cause: validationError });\n}\n\nexport async function updateCommand(options: UpdateOptions, overrides: Partial<Dependencies> = {}): Promise<void> {\n  const paths = overrides.paths ?? resolveInstallStorePaths();\n  const executablePath = overrides.executablePath ?? process.argv[1] ?? \"\";\n  const runCommand = overrides.runCommand ?? execFileAsync;\n  const mode = detectInstallMode(executablePath, paths);\n  const manifest = readInstallManifest(paths);\n  if (options.rollback) {\n    if (mode !== \"managed\") throw new Error(\"--rollback is only available for managed installs.\");\n    if (options.dryRun) { emit(options, { mode, action: \"rollback\", dryRun: true, target: manifest?.previous[0]?.version ?? null }, `Would roll back to ${manifest?.previous[0]?.version ?? \"the previous payload\"}.`); return; }\n    const next = await withInstallStoreLock(async () => rollbackManagedInstall(paths), paths);\n    const restarted = await (overrides.restartActiveService ?? restartActiveManagedService)(next.version);","sourceCodeStart":141,"sourceCodeEnd":177,"githubUrl":"https://github.com/paperclipai/paperclip/blob/67001ec6eb96ae601aa27bc91d9b2415d665334a/cli/src/commands/update.ts#L141-L177","documentation":"Thrown by rollbackAfterServiceValidationFailure when, after a newly updated payload fails to start its service, the automatic rollback to the prior version is performed but restarting the rolled-back service also throws. This is the worst-case recovery failure: both the new and the old payload are unable to run the service. The error bundles both the original validation error and the restart error in an AggregateError as `cause`.","triggerScenarios":"An update (git or npm payload) installs successfully, restartActiveManagedService throws on the new version, rollbackAfterServiceValidationFailure rolls back to manifest.previous[0], and the restart call for that rolled-back version throws too. Reached via the catch blocks around lines 203-211 and 257-265 in updateCommand.","commonSituations":"System-wide breakage affecting all versions — e.g. systemd/launchd itself broken, port conflict on every version, shared DB schema already migrated and incompatible with the old binary, or corrupted payload directories for both versions.","solutions":["Inspect the AggregateError cause: both the original validation error and the restart error tell you what is broken system-wide (fix that root cause first).","Start the database/service manager and confirm the service unit is loadable: `systemctl --user status paperclipai*` / `launchctl list | grep paperclip`.","Restore the pre-update database backup if the failure is schema/migration related (the old binary cannot start against the migrated DB).","Manually point the `current` symlink at a known-good payload and `paperclipai service restart`, or reinstall with `paperclipai install`."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  await updateCommand(options);\n} catch (error) {\n  if (error instanceof Error && error.message.includes('rolled-back service also failed to restart') && error.cause instanceof AggregateError) {\n    const [validationErr, restartErr] = error.cause.errors;\n    // both versions are broken — surface both, restore DB backup, and reinstall a known-good payload\n    console.error('Validation failure:', validationErr);\n    console.error('Restart failure:', restartErr);\n    await restorePreUpdateBackup();\n    await installCommand({ version: knownGoodVersion });\n  } else throw error;\n}","preventionTips":["Always let the pre-update backup run (default) so you can restore when both payloads fail.","Validate new releases on a staging instance before updating production.","Keep systemd/launchd healthy — a broken service manager makes every version fail to start.","Pin to a known-good version with `paperclipai update --version` rather than always chasing latest."],"tags":["rollback","service-failure","update","recovery"],"backgroundTag":null,"analyzedSha":"67001ec6eb96ae601aa27bc91d9b2415d665334a","analyzedAt":"2026-08-12T12:05:45.408Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}