paperclipai/paperclip · error

${manager.serviceName} is still loaded after uninstall.

Error message

${manager.serviceName} is still loaded after uninstall.

What it means

Thrown by the `service uninstall` action after calling manager.uninstall() and re-checking status: the service is still reported as installed or active, meaning uninstall did not fully remove it. This catches supervisor cleanup failures.

Source

Thrown at cli/src/commands/service.ts:191

    .action(async (opts) => {
      const manager = await resolveManager(opts); if (!manager) return;
      const result = await manager.install({ startNow: opts.startNow, startOnLogin: opts.startOnLogin });
      let lingerEnabled = false;
      if (manager.enableLinger) {
        let consent = opts.enableLinger === true;
        if (!consent && process.stdin.isTTY && process.stdout.isTTY) {
          consent = await p.confirm({ message: "Allow Paperclip to run without an active login session? This runs 'loginctl enable-linger' for your user and may request system authorization.", initialValue: false }) === true;
        }
        if (consent) { await manager.enableLinger(); lingerEnabled = true; }
      }
      output({ installed: true, changed: result.changed, platform: manager.platform, serviceName: manager.serviceName, definitionPath: manager.definitionPath, lingerEnabled }, opts.json);
    });

  common(service.command("uninstall").description("Stop, disable, and remove the background service")).action(async (opts) => {
    const manager = await resolveManager(opts); if (!manager) return;
    await manager.uninstall();
    const status = await manager.status();
    if (status.installed || status.active) throw new Error(`${manager.serviceName} is still loaded after uninstall.`);
    output({ uninstalled: true, serviceName: manager.serviceName }, opts.json);
  });

  for (const verb of ["start", "stop"] as const) {
    common(service.command(verb).description(`${verb === "start" ? "Start" : "Stop"} the background service`)).action(async (opts) => {
      const manager = await resolveManager(opts); if (!manager) return;
      await manager[verb]();
      output(await manager.status(), opts.json);
    });
  }

  common(service.command("restart").description("Hot-restart the service while preserving active agent runs"))
    .option("--wait", "Wait for active runs to drain instead of adopting them", false)
    .option("--expected-version <version>", "Require the restarted server to report this version")
    .action(async (opts) => output(await restartManagedService({ instanceId: opts.instance, expectedVersion: opts.expectedVersion, waitForDrain: opts.wait }), opts.json));

  common(service.command("status").description("Show supervisor and health status")).action(async (opts) => {
    const manager = await resolveManager(opts); if (!manager) return;

View on GitHub (pinned to 67001ec6eb)

Solutions

  1. Stop the service explicitly first: `paperclipai service stop`, then uninstall again.
  2. Remove the unit file manually if permissions blocked it (the definitionPath is in manager output); may need elevated privileges.
  3. Re-run `paperclipai service status` to see residual state, then `paperclipai service uninstall` again.
  4. Check manager logs for the underlying uninstall error.

Example fix

# before
paperclipai service uninstall  # still loaded
# after
paperclipai service stop
sudo rm "$(paperclipai service status | jq -r .definitionPath)"
paperclipai service uninstall
Defensive patterns

Strategy: try-catch

Validate before calling

async function ensureUninstalled(manager: ServiceManager): Promise<void> {
  await manager.uninstall();
  const s = await manager.status();
  if (s.installed || s.active) throw new Error(`${manager.serviceName} still loaded.`);
}

Try / catch

try {
  await manager.uninstall();
} catch (err) {
  console.error('Uninstall failed; stop service then retry:', err);
  await manager.stop();
  await manager.uninstall();
}

Prevention

When it happens

Trigger: Running `paperclipai service uninstall` where the manager's uninstall returned but `status()` still reports `installed` or `active`. Causes: unit file left on disk, service still running because stop failed, permission denied removing the unit, or the supervisor cache is stale.

Common situations: Permission issues removing a system unit (needs sudo), service busy with active connections so it could not stop, a second install raced the uninstall, or a partially-managed unit the manager cannot fully remove.

Related errors


AI-assisted analysis of paperclipai/paperclip@67001ec6eb (2026-08-12). Data as JSON: /api/errors/83c25ffcda82c3b0. Report an issue: GitHub.