{"record":{"id":"85375cdf4c62551c","repo":"paperclipai/paperclip","slug":"refusing-to-replace-non-symlink-paths-currentpat","errorCode":null,"errorMessage":"Refusing to replace non-symlink ${paths.currentPath}.","messagePattern":"Refusing to replace non-symlink (.+?)\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cli/src/install-store.ts","lineNumber":273,"sourceCode":"  }\n  const installsRealPath = fs.realpathSync(paths.installsRoot);\n  const payloadRealPath = fs.realpathSync(payloadPath);\n  if (!payloadRealPath.startsWith(`${installsRealPath}${path.sep}`)) {\n    throw new Error(`Refusing to activate payload that resolves outside ${paths.installsRoot}.`);\n  }\n}\n\nexport function flipCurrentAtomic(\n  payloadPath: string,\n  paths = resolveInstallStorePaths(),\n  hooks: { beforeRename?: () => void } = {},\n): void {\n  assertPayloadPath(payloadPath, paths);\n  ensurePrivateDirectory(paths.cliRoot);\n  try {\n    const currentStat = fs.lstatSync(paths.currentPath);\n    if (!currentStat.isSymbolicLink()) {\n      throw new Error(`Refusing to replace non-symlink ${paths.currentPath}.`);\n    }\n  } catch (error) {\n    if ((error as NodeJS.ErrnoException).code !== \"ENOENT\") throw error;\n  }\n\n  const temporaryLink = path.join(\n    paths.cliRoot,\n    `.current-${process.pid}-${Date.now()}-${Math.random().toString(16).slice(2)}`,\n  );\n  const relativeTarget = path.relative(paths.cliRoot, payloadPath);\n  try {\n    fs.symlinkSync(relativeTarget, temporaryLink, \"dir\");\n    hooks.beforeRename?.();\n    fs.renameSync(temporaryLink, paths.currentPath);\n  } finally {\n    fs.rmSync(temporaryLink, { force: true });\n  }\n}","sourceCodeStart":255,"sourceCodeEnd":291,"githubUrl":"https://github.com/paperclipai/paperclip/blob/01ad8584922b5d85292b1723cae71fa0d9b07a19/cli/src/install-store.ts#L255-L291","documentation":"flipCurrentAtomic found an existing entry at the 'current' path that is not a symlink; it only ever atomically replaces a symlink and refuses to delete other file types.","triggerScenarios":"Thrown at cli/src/install-store.ts:273 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":["Remove the non-symlink at ${paths.currentPath} manually after verifying it is safe, then retry."],"exampleFix":null,"handlingStrategy":"validation","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"analyzedSha":"01ad8584922b5d85292b1723cae71fa0d9b07a19","analyzedAt":"2026-08-18T22:49:45.177Z","contentChangedAt":"2026-08-18T22:49:45.177Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}