paperclipai/paperclip · error · Error
Refusing to replace existing non-managed command ${paths.shi
Error message
Refusing to replace existing non-managed command ${paths.shimPath}. What it means
Thrown by assertManagedShimWritable when the existing shim file's contents do not match the managed shim format (checked by isManagedShimContents, which validates a 5-line structure: shebang, marker comment, set -eu, exec line, trailing newline). This prevents the installer from silently overwriting a user-installed binary, a different tool's executable, or a manually-edited shim that no longer matches the managed format.
Source
Thrown at cli/src/install-store.ts:370
const homeDir = path.dirname(path.dirname(path.dirname(paths.shimPath)));
for (const directoryPath of [homeDir, path.join(homeDir, ".local"), path.dirname(paths.shimPath)]) {
if (!fs.existsSync(directoryPath)) continue;
const directoryStat = fs.lstatSync(directoryPath);
if (!directoryStat.isDirectory() || directoryStat.isSymbolicLink()) {
throw new Error(`Refusing to use unsafe shim directory ${directoryPath}.`);
}
assertOwnedByCurrentUser(directoryStat, directoryPath);
}
try {
const stat = fs.lstatSync(paths.shimPath);
if (!stat.isFile() || stat.isSymbolicLink()) {
throw new Error(`Refusing to replace non-regular shim ${paths.shimPath}.`);
}
assertOwnedByCurrentUser(stat, paths.shimPath);
if (stat.nlink > 1) throw new Error(`Refusing to replace multiply linked shim ${paths.shimPath}.`);
const existing = fs.readFileSync(paths.shimPath, "utf8");
if (!isManagedShimContents(existing)) {
throw new Error(`Refusing to replace existing non-managed command ${paths.shimPath}.`);
}
} catch (error) {
if ((error as NodeJS.ErrnoException).code !== "ENOENT") throw error;
}
}
function shellQuote(value: string): string {
return `'${value.replace(/'/g, `'"'"'`)}'`;
}
function isManagedShimContents(contents: string): boolean {
const lines = contents.split("\n");
return (
lines.length === 5 &&
lines[0] === "#!/bin/sh" &&
lines[1] === `# ${MANAGED_SHIM_MARKER}` &&
lines[2] === "set -eu" &&
/^exec '(?:[^']|'"'"')+' '(?:[^']|'"'"')+' "\$@"$/.test(lines[3]) &&View on GitHub (pinned to 67001ec6eb)
Solutions
- Inspect the existing shim: 'cat ~/.local/bin/paperclipai' to see what it contains.
- If it is not a paperclip-managed shim, back it up and remove it: 'mv ~/.local/bin/paperclipai ~/.local/bin/paperclipai.bak'.
- If it is an older paperclip shim format, remove it so the installer can write the current format.
- Re-run the install command to write a fresh managed shim.
Example fix
// before: ~/.local/bin/paperclipai is a user script // cat ~/.local/bin/paperclipai -> #!/usr/bin/env node ... (custom script) // after: back up and remove, then reinstall // mv ~/.local/bin/paperclipai ~/.local/bin/paperclipai.bak // re-run: paperclipai install
Defensive patterns
Strategy: validation
Validate before calling
import fs from 'node:fs';
const MANAGED_SHIM_MARKER = 'paperclipai managed install shim v1';
function isManagedShim(shimPath: string): boolean {
try {
const contents = fs.readFileSync(shimPath, 'utf8');
const lines = contents.split('\n');
return (
lines.length === 5 &&
lines[0] === '#!/bin/sh' &&
lines[1] === `# ${MANAGED_SHIM_MARKER}` &&
lines[2] === 'set -eu' &&
/^exec '(?:[^']|'"'"')+' '(?:[^']|'"'"')+' "\$@"$/.test(lines[3]) &&
lines[4] === ''
);
} catch {
return false;
}
}
// Call before writeManagedShim:
if (fs.existsSync(paths.shimPath) && !isManagedShim(paths.shimPath)) {
console.warn('Existing shim is not managed by paperclipai; backing up before overwrite.');
fs.renameSync(paths.shimPath, `${paths.shimPath}.user-backup`);
} Try / catch
try {
writeManagedShim(paths);
} catch (error) {
if (error instanceof Error && error.message.includes('non-managed command')) {
// The path has a non-paperclip binary/script; back it up and retry
const backup = `${paths.shimPath}.${Date.now()}.bak`;
fs.renameSync(paths.shimPath, backup);
console.warn(`Backed up existing command to ${backup}`);
writeManagedShim(paths); // retry
} else {
throw error;
}
} Prevention
- Check whether another tool or package installed a binary named 'paperclipai' before running install.
- If you have a custom script at the shim path, move it to a different name before installing.
- The managed shim has a recognizable 5-line format with the marker 'paperclipai managed install shim v1'—if the existing file doesn't match, back it up first.
When it happens
Trigger: Calling assertManagedShimWritable or writeManagedShim when ~/.local/bin/paperclipai exists as a regular file but its contents are not the recognizable 5-line managed shim (e.g., it's a compiled binary, a script from another tool, or a manually customized shim).
Common situations: A different version of paperclipai installed a shim with a different format. A user placed their own script named 'paperclipai' in ~/.local/bin. A package manager installed a different binary at the same path. The managed shim was manually edited, breaking the format check.
Related errors
- Refusing to use unsafe shim directory ${directoryPath}.
- Refusing to replace non-regular shim ${paths.shimPath}.
- Refusing to replace multiply linked shim ${paths.shimPath}.
- Safety checks failed. Resolve the issues above or re-run wit
- Refusing to use non-directory install-store path ${directory
AI-assisted analysis of paperclipai/paperclip@67001ec6eb (2026-08-12).
Data as JSON: /api/errors/be6e30d60cb4839c.
Report an issue: GitHub.