{"record":{"id":"be6e30d60cb4839c","repo":"paperclipai/paperclip","slug":"refusing-to-replace-existing-non-managed-command","errorCode":null,"errorMessage":"Refusing to replace existing non-managed command ${paths.shimPath}.","messagePattern":"Refusing to replace existing non-managed command (.+?)\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"cli/src/install-store.ts","lineNumber":370,"sourceCode":"  const homeDir = path.dirname(path.dirname(path.dirname(paths.shimPath)));\n  for (const directoryPath of [homeDir, path.join(homeDir, \".local\"), path.dirname(paths.shimPath)]) {\n    if (!fs.existsSync(directoryPath)) continue;\n    const directoryStat = fs.lstatSync(directoryPath);\n    if (!directoryStat.isDirectory() || directoryStat.isSymbolicLink()) {\n      throw new Error(`Refusing to use unsafe shim directory ${directoryPath}.`);\n    }\n    assertOwnedByCurrentUser(directoryStat, directoryPath);\n  }\n  try {\n    const stat = fs.lstatSync(paths.shimPath);\n    if (!stat.isFile() || stat.isSymbolicLink()) {\n      throw new Error(`Refusing to replace non-regular shim ${paths.shimPath}.`);\n    }\n    assertOwnedByCurrentUser(stat, paths.shimPath);\n    if (stat.nlink > 1) throw new Error(`Refusing to replace multiply linked shim ${paths.shimPath}.`);\n    const existing = fs.readFileSync(paths.shimPath, \"utf8\");\n    if (!isManagedShimContents(existing)) {\n      throw new Error(`Refusing to replace existing non-managed command ${paths.shimPath}.`);\n    }\n  } catch (error) {\n    if ((error as NodeJS.ErrnoException).code !== \"ENOENT\") throw error;\n  }\n}\n\nfunction shellQuote(value: string): string {\n  return `'${value.replace(/'/g, `'\"'\"'`)}'`;\n}\n\nfunction isManagedShimContents(contents: string): boolean {\n  const lines = contents.split(\"\\n\");\n  return (\n    lines.length === 5 &&\n    lines[0] === \"#!/bin/sh\" &&\n    lines[1] === `# ${MANAGED_SHIM_MARKER}` &&\n    lines[2] === \"set -eu\" &&\n    /^exec '(?:[^']|'\"'\"')+' '(?:[^']|'\"'\"')+' \"\\$@\"$/.test(lines[3]) &&","sourceCodeStart":352,"sourceCodeEnd":388,"githubUrl":"https://github.com/paperclipai/paperclip/blob/67001ec6eb96ae601aa27bc91d9b2415d665334a/cli/src/install-store.ts#L352-L388","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","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."],"exampleFix":"// before: ~/.local/bin/paperclipai is a user script\n// cat ~/.local/bin/paperclipai -> #!/usr/bin/env node ... (custom script)\n\n// after: back up and remove, then reinstall\n// mv ~/.local/bin/paperclipai ~/.local/bin/paperclipai.bak\n// re-run: paperclipai install","handlingStrategy":"validation","validationCode":"import fs from 'node:fs';\n\nconst MANAGED_SHIM_MARKER = 'paperclipai managed install shim v1';\n\nfunction isManagedShim(shimPath: string): boolean {\n  try {\n    const contents = fs.readFileSync(shimPath, 'utf8');\n    const lines = contents.split('\\n');\n    return (\n      lines.length === 5 &&\n      lines[0] === '#!/bin/sh' &&\n      lines[1] === `# ${MANAGED_SHIM_MARKER}` &&\n      lines[2] === 'set -eu' &&\n      /^exec '(?:[^']|'\"'\"')+' '(?:[^']|'\"'\"')+' \"\\$@\"$/.test(lines[3]) &&\n      lines[4] === ''\n    );\n  } catch {\n    return false;\n  }\n}\n\n// Call before writeManagedShim:\nif (fs.existsSync(paths.shimPath) && !isManagedShim(paths.shimPath)) {\n  console.warn('Existing shim is not managed by paperclipai; backing up before overwrite.');\n  fs.renameSync(paths.shimPath, `${paths.shimPath}.user-backup`);\n}","typeGuard":null,"tryCatchPattern":"try {\n  writeManagedShim(paths);\n} catch (error) {\n  if (error instanceof Error && error.message.includes('non-managed command')) {\n    // The path has a non-paperclip binary/script; back it up and retry\n    const backup = `${paths.shimPath}.${Date.now()}.bak`;\n    fs.renameSync(paths.shimPath, backup);\n    console.warn(`Backed up existing command to ${backup}`);\n    writeManagedShim(paths); // retry\n  } else {\n    throw error;\n  }\n}","preventionTips":["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."],"tags":["install-store","shim","safety","cli"],"backgroundTag":null,"analyzedSha":"67001ec6eb96ae601aa27bc91d9b2415d665334a","analyzedAt":"2026-08-12T12:05:45.408Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}