{"record":{"id":"14d9e13eeb8b1a69","repo":"paperclipai/paperclip","slug":"refusing-to-replace-non-regular-shim-paths-shimp","errorCode":null,"errorMessage":"Refusing to replace non-regular shim ${paths.shimPath}.","messagePattern":"Refusing to replace non-regular shim (.+?)\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"cli/src/install-store.ts","lineNumber":364,"sourceCode":"    }\n  }\n  return removed;\n}\n\nexport function assertManagedShimWritable(paths = resolveInstallStorePaths()): void {\n  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\");","sourceCodeStart":346,"sourceCodeEnd":382,"githubUrl":"https://github.com/paperclipai/paperclip/blob/67001ec6eb96ae601aa27bc91d9b2415d665334a/cli/src/install-store.ts#L346-L382","documentation":"Thrown by assertManagedShimWritable when paths.shimPath exists but is not a regular file (it is a symlink, socket, device node, or other special file). The installer must only overwrite its own regular-file shim; refusing to replace a non-regular file prevents clobbering symlinks, sockets, or other special objects that a user may have intentionally placed at that path.","triggerScenarios":"Calling assertManagedShimWritable or writeManagedShim when ~/.local/bin/paperclipai exists but is a symlink, named pipe, socket, device file, or any non-regular-file type.","commonSituations":"A user or package manager created ~/.local/bin/paperclipai as a symlink to another binary. A dotfile manager symlinked the shim. A different tool placed a non-file object at that path.","solutions":["Inspect the shim: 'ls -la ~/.local/bin/paperclipai' to see its type.","If it is a symlink to an unmanaged binary, remove it so the installer can create its managed shim: 'rm ~/.local/bin/paperclipai'.","If it is a symlink to the correct managed location, resolve the real path and verify it matches the expected shim format, then remove the symlink.","Re-run the install to write a fresh regular-file shim."],"exampleFix":"// before: shim is a symlink\n// ls -la ~/.local/bin/paperclipai -> lrwxrwxrwx -> /opt/paperclip/bin/paperclipai\n\n// after: remove symlink so installer writes a regular file\n// rm ~/.local/bin/paperclipai\n// re-run: paperclipai install","handlingStrategy":"validation","validationCode":"import fs from 'node:fs';\n\nfunction isShimRegularFile(shimPath: string): boolean {\n  try {\n    const stat = fs.lstatSync(shimPath);\n    return stat.isFile() && !stat.isSymbolicLink();\n  } catch (error) {\n    return (error as NodeJS.ErrnoException).code === 'ENOENT';\n  }\n}\n\n// Call before writeManagedShim:\nif (!isShimRegularFile(paths.shimPath)) {\n  console.warn('Existing shim is not a regular file; removing it before install.');\n  fs.rmSync(paths.shimPath, { force: true });\n}","typeGuard":null,"tryCatchPattern":"try {\n  writeManagedShim(paths);\n} catch (error) {\n  if (error instanceof Error && error.message.includes('non-regular shim')) {\n    // The shim path is a symlink or special file; back it up and remove\n    fs.renameSync(paths.shimPath, `${paths.shimPath}.bak`);\n  }\n  throw error;\n}","preventionTips":["Ensure ~/.local/bin/paperclipai does not exist as a symlink before installing.","If a package manager installed a different binary at that path, uninstall it first.","Run 'ls -la ~/.local/bin/paperclipai' before install to verify the path is clear or contains a managed shim."],"tags":["security","install-store","shim","cli"],"backgroundTag":null,"analyzedSha":"67001ec6eb96ae601aa27bc91d9b2415d665334a","analyzedAt":"2026-08-12T12:05:45.408Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}