paperclipai/paperclip · error

Refusing to replace service definition not owned by the curr

Error message

Refusing to replace service definition not owned by the current user: ${filePath}.

What it means

The existing service definition file is not owned by the current user, so the guard refuses to modify definitions belonging to another user or the system.

Source

Thrown at cli/src/services/service-manager.ts:148

  <key>ExitTimeOut</key><integer>300</integer>
  <key>StandardOutPath</key><string>${escapeXml(input.stdoutPath)}</string>
  <key>StandardErrorPath</key><string>${escapeXml(input.stderrPath)}</string>
</dict>
</plist>
`;
}

async function writeIfChanged(filePath: string, contents: string): Promise<boolean> {
  const directoryPath = path.dirname(filePath);
  await fs.mkdir(directoryPath, { recursive: true, mode: 0o700 });
  const directoryStat = await fs.lstat(directoryPath);
  if (!directoryStat.isDirectory() || directoryStat.isSymbolicLink()) throw new Error(`Refusing to write service definition through unsafe directory ${directoryPath}.`);
  const currentUid = process.getuid?.();
  if (currentUid !== undefined && directoryStat.uid !== currentUid) throw new Error(`Refusing to write service definition in directory not owned by the current user: ${directoryPath}.`);
  try {
    const stat = await fs.lstat(filePath);
    if (!stat.isFile() || stat.isSymbolicLink() || stat.nlink > 1) throw new Error(`Refusing to replace unsafe service definition ${filePath}.`);
    if (currentUid !== undefined && stat.uid !== currentUid) throw new Error(`Refusing to replace service definition not owned by the current user: ${filePath}.`);
    if (await fs.readFile(filePath, "utf8") === contents) return false;
  } catch (error) {
    if ((error as NodeJS.ErrnoException).code !== "ENOENT") throw error;
  }
  const temporaryPath = path.join(directoryPath, `.${path.basename(filePath)}.tmp-${process.pid}-${Date.now()}`);
  try {
    await fs.writeFile(temporaryPath, contents, { encoding: "utf8", mode: 0o644, flag: "wx" });
    await fs.rename(temporaryPath, filePath);
  } finally {
    await fs.rm(temporaryPath, { force: true });
  }
  return true;
}

export class SystemdServiceManager implements ServiceManager {
  readonly platform = "systemd" as const;
  readonly serviceName: string;
  readonly definitionPath: string;

View on GitHub (pinned to 120ae5428f)

Solutions

  1. Change ownership of ${filePath} to the current user, or remove it and let the manager recreate it.
Defensive patterns

Strategy: validation

When it happens

Trigger: Thrown at cli/src/services/service-manager.ts:148 when the library encounters an invalid state.

Common situations: See trigger scenarios.


AI-assisted analysis of paperclipai/paperclip@120ae5428f (2026-08-18). Data as JSON: /api/errors/3310dce4b9845b81. Report an issue: GitHub.