paperclipai/paperclip · error

${detection.reason}

Error message

${detection.reason}

What it means

Thrown by restartManagedService() when detectServiceManager() returns `{supported: false}`. The message is the detection's own `reason` string, which explains why no supported service supervisor (systemd on Linux, launchd on macOS) was found for this instance.

Source

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

  const reportPath = path.join(resolvePaperclipInstanceRoot(instanceId), "hot-restart-report.json");
  const deadline = Date.now() + timeoutMs;
  while (Date.now() < deadline) {
    try {
      const report = JSON.parse(await fs.readFile(reportPath, "utf8")) as { requestedAt?: unknown };
      if (report.requestedAt === requestedAt) return report;
    } catch (error) {
      if ((error as NodeJS.ErrnoException).code !== "ENOENT") throw error;
    }
    await new Promise((resolve) => setTimeout(resolve, 250));
  }
  return null;
}

export async function restartManagedService(input: { instanceId?: string; expectedVersion?: string | null; waitForDrain?: boolean } = {}): Promise<{ status: ServiceStatus; health: HealthResult; report: unknown | null }> {
  const instanceId = resolvePaperclipInstanceId(input.instanceId);
  return withHotRestartLock(instanceId, async () => {
    const detection = await detectServiceManager({ instanceId });
    if (!detection.supported) throw new Error(detection.reason);
    const before = await detection.manager.status();
    const intent = await writeHotRestartIntent(before, instanceId, input.waitForDrain ?? false);
    await detection.manager.restart();
    const health = await waitForHealth(instanceId, resolveRestartExpectedVersion(input.expectedVersion));
    return { status: await detection.manager.status(), health, report: await waitForRestartReport(instanceId, intent.requestedAt) };
  });
}

export function registerServiceCommands(program: Command): void {
  const service = program.command("service").description("Manage Paperclip as a background service");
  const common = (command: Command) => command.option("-i, --instance <id>", "Local instance id (default: default)").option("--json", "Print machine-readable JSON", false);

  common(service.command("install").description("Install and register the background service"))
    .option("--no-start-now", "Install without starting now")
    .option("--no-start-on-login", "Install without enabling start on login")
    .option("--enable-linger", "Allow systemd startup without an active login session", false)
    .action(async (opts) => {
      const manager = await resolveManager(opts); if (!manager) return;

View on GitHub (pinned to 67001ec6eb)

Solutions

  1. Install the service first: `paperclipai service install`.
  2. On Linux without systemd, enable systemd (WSL: `/etc/wsl.conf` `[boot] systemd=true`) or run the server in the foreground with `paperclipai run`.
  3. Read detection.reason for the platform-specific cause and address it.

Example fix

# before: restart on unsupported platform
paperclipai service restart
# after: install, or run foreground
paperclipai service install
paperclipai service restart
# or
paperclipai run
Defensive patterns

Strategy: validation

Validate before calling

const detection = await detectServiceManager({instanceId});
if (!detection.supported) {
  throw new Error(`Service manager unsupported: ${detection.reason}`);
}

Prevention

When it happens

Trigger: Running `paperclipai service restart` on a platform without systemd or launchd, or where the service was never installed, or detection cannot find the unit. The thrown value is `detection.reason` produced by detectServiceManager().

Common situations: Unsupported OS (e.g. Windows or a minimal container without systemd/launchd), WSL without systemd enabled, or attempting service commands before `service install` has been run.

Related errors


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