paperclipai/paperclip · critical · Error
Refusing to modify path not owned by the current user: ${tar
Error message
Refusing to modify path not owned by the current user: ${targetPath}. What it means
Thrown by assertOwnedByCurrentUser() when a file or directory's stat.uid does not equal process.getuid(). The install store only modifies entries it owns to prevent one user from writing into another user's store (privilege escalation / cross-user tampering). The check is skipped on platforms without process.getuid (e.g. Windows).
Source
Thrown at cli/src/install-store.ts:53
markerPath: string;
lockPath: string;
currentPath: string;
shimPath: string;
};
function ensurePrivateDirectory(directoryPath: string): void {
fs.mkdirSync(directoryPath, { recursive: true, mode: 0o700 });
const stat = fs.lstatSync(directoryPath);
if (!stat.isDirectory() || stat.isSymbolicLink()) {
throw new Error(`Refusing to use non-directory install-store path ${directoryPath}.`);
}
fs.chmodSync(directoryPath, 0o700);
}
function assertOwnedByCurrentUser(stat: fs.Stats, targetPath: string): void {
const getuid = process.getuid;
if (typeof getuid === "function" && stat.uid !== getuid()) {
throw new Error(`Refusing to modify path not owned by the current user: ${targetPath}.`);
}
}
function writeFileAtomic(filePath: string, contents: string, mode: number): void {
const temporaryPath = path.join(
path.dirname(filePath),
`.${path.basename(filePath)}.tmp-${process.pid}-${Date.now()}-${Math.random().toString(16).slice(2)}`,
);
try {
fs.writeFileSync(temporaryPath, contents, { mode, flag: "wx" });
fs.renameSync(temporaryPath, filePath);
} finally {
fs.rmSync(temporaryPath, { force: true });
}
}
export function resolveInstallStorePaths(options: {
paperclipHome?: string;View on GitHub (pinned to 67001ec6eb)
Solutions
- Run the CLI as the same user that owns the files ('chown' the store to the current user, or run without sudo).
- Fix ownership: 'sudo chown -R $(id -u):$(id -g) ~/.paperclip/cli'.
- In containers, ensure the volume mount is chowned to the container user's uid at image/mount time.
- Avoid running managed installs as root when the store was created by a non-root user.
Example fix
// before: files owned by uid 1000, running as root (uid 0) $ sudo paperclipai install # throws // after: chown store to current user, run as that user $ sudo chown -R $(id -u):$(id -g) ~/.paperclip/cli $ paperclipai install
Defensive patterns
Strategy: validation
Validate before calling
import fs from "node:fs";
function ownedByCurrentUser(p: string): boolean {
const getuid = process.getuid;
if (typeof getuid !== "function") return true; // platforms without uid
try { return fs.lstatSync(p).uid === getuid(); } catch { return false; }
}
// Before install ops:
if (!ownedByCurrentUser(paths.cliRoot)) {
console.error(`Run 'sudo chown -R $(id -u):$(id -g) ${paths.cliRoot}'`);
} Type guard
import fs from "node:fs";
function isOwnedByCurrentUser(p: string): boolean {
const getuid = process.getuid;
if (typeof getuid !== "function") return true;
try { return fs.statSync(p).uid === getuid(); } catch { return false; }
} Try / catch
try {
assertManagedInstallStore(paths);
} catch (err) {
if (err instanceof Error && err.message.includes("not owned by the current user")) {
console.error("Fix ownership with: sudo chown -R $(id -u):$(id -g) ~/.paperclip/cli");
process.exit(1);
}
throw err;
} Prevention
- Run the CLI as the same OS user that owns ~/.paperclip.
- Avoid 'sudo paperclipai install' unless the entire store is root-owned.
- In containers, chown the mounted volume to the container uid.
- After restoring from tarball, chown -R to the target user.
When it happens
Trigger: Any install-store operation that calls assertOwnedByCurrentUser on a path whose owning uid differs from the current process uid. This includes marker files, cliRoot, shim path, and shell rc files during addManagedPathBlock/removeManagedPathBlock.
Common situations: 1) Running the CLI under 'sudo' or as root after a prior install was done as a normal user (root's uid 0 != file owner uid). 2) Two distinct OS users sharing a HOME. 3) Files restored from a tarball that preserved a different uid. 4) A container where the mounted volume is owned by a host uid that differs from the container user.
Related errors
- Refusing to use non-directory install-store path ${directory
- Refusing to activate non-directory payload ${payloadPath}.
- Refusing to use unsafe install-store marker ${paths.markerPa
- Refusing to use unrecognized install store ${paths.cliRoot}.
- Refusing to remove unsafe install-store path ${paths.cliRoot
AI-assisted analysis of paperclipai/paperclip@67001ec6eb (2026-08-12).
Data as JSON: /api/errors/753e532c60288fc9.
Report an issue: GitHub.