{"record":{"id":"edce6e63082b08a0","repo":"paperclipai/paperclip","slug":"refusing-to-remove-unverified-install-store-path","errorCode":null,"errorMessage":"Refusing to remove unverified install store ${paths.cliRoot}.","messagePattern":"Refusing to remove unverified install store (.+?)\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"critical","filePath":"cli/src/install-store.ts","lineNumber":127,"sourceCode":"      ) {\n        throw writeError;\n      }\n    }\n  }\n}\n\nexport function assertManagedInstallStore(paths = resolveInstallStorePaths()): InstallManifest {\n  const cliStat = fs.lstatSync(paths.cliRoot);\n  if (!cliStat.isDirectory() || cliStat.isSymbolicLink()) {\n    throw new Error(`Refusing to remove unsafe install-store path ${paths.cliRoot}.`);\n  }\n  assertOwnedByCurrentUser(cliStat, paths.cliRoot);\n  let markerStat: fs.Stats;\n  try {\n    markerStat = fs.lstatSync(paths.markerPath);\n  } catch (error) {\n    if ((error as NodeJS.ErrnoException).code === \"ENOENT\") {\n      throw new Error(`Refusing to remove unverified install store ${paths.cliRoot}.`);\n    }\n    throw error;\n  }\n  if (!markerStat.isFile() || markerStat.isSymbolicLink() || markerStat.nlink > 1) {\n    throw new Error(`Refusing to remove unverified install store ${paths.cliRoot}.`);\n  }\n  assertOwnedByCurrentUser(markerStat, paths.markerPath);\n  if (fs.readFileSync(paths.markerPath, \"utf8\") !== MANAGED_STORE_MARKER) {\n    throw new Error(`Refusing to remove unverified install store ${paths.cliRoot}.`);\n  }\n  const manifest = readInstallManifest(paths);\n  if (!manifest) throw new Error(`Refusing to remove install store without a manifest at ${paths.cliRoot}.`);\n  const relativePayload = path.relative(paths.installsRoot, path.resolve(manifest.payloadPath));\n  if (!relativePayload || relativePayload.startsWith(\"..\") || path.isAbsolute(relativePayload)) {\n    throw new Error(`Refusing to remove install store with an invalid manifest at ${paths.cliRoot}.`);\n  }\n  return manifest;\n}","sourceCodeStart":109,"sourceCodeEnd":145,"githubUrl":"https://github.com/paperclipai/paperclip/blob/67001ec6eb96ae601aa27bc91d9b2415d665334a/cli/src/install-store.ts#L109-L145","documentation":"Thrown by assertManagedInstallStore() when attempting to lstatSync the marker file fails with ENOENT — the marker file (.managed-install) does not exist at all. Without a valid marker the library cannot confirm the store is Paperclip-managed, so it refuses to proceed with removal. The message is shared with two other checks (lines 132, 136) but this specific throw is the missing-file case.","triggerScenarios":"Called assertManagedInstallStore() where paths.markerPath does not exist on disk (the catch around lstatSync rethrows with ENOENT mapped to this refusal).","commonSituations":"1) The store directory exists but the marker was manually deleted. 2) A partial uninstall removed the marker but left cliRoot. 3) The directory was hand-created without going through initializeInstallStore. 4) A sync tool excluded the dotfile marker.","solutions":["If the store is stale, remove the entire cliRoot manually ('rm -rf ~/.paperclip/cli') since the library cannot safely verify it.","If you want to keep the store, run initializeInstallStore() (or 'paperclipai install') to write a fresh marker — but only if you trust the directory contents.","Restore the marker from a known-good backup if available.","Do not fabricate a marker by hand unless you are certain the directory is a genuine Paperclip store."],"exampleFix":"$ ls ~/.paperclip/cli/.managed-install\nls: .managed-install: No such file or directory\n$ rm -rf ~/.paperclip/cli\n$ paperclipai install   # recreates store + marker","handlingStrategy":"validation","validationCode":"import fs from \"node:fs\";\nimport { resolveInstallStorePaths } from \"./install-store.js\";\n\nfunction markerExists(paths = resolveInstallStorePaths()): boolean {\n  try { fs.lstatSync(paths.markerPath); return true; } catch { return false; }\n}","typeGuard":"import fs from \"node:fs\";\n\nfunction markerPresent(markerPath: string): boolean {\n  try { fs.lstatSync(markerPath); return true; } catch (e) {\n    return (e as NodeJS.ErrnoException).code !== \"ENOENT\";\n  }\n}","tryCatchPattern":"try {\n  assertManagedInstallStore(paths);\n} catch (err) {\n  if (err instanceof Error && err.message.includes(\"unverified install store\")) {\n    console.error(\"Marker missing. To reset: rm -rf ~/.paperclip/cli && paperclipai install\");\n    process.exit(1);\n  }\n  throw err;\n}","preventionTips":["Do not delete the .managed-install marker manually.","Use initializeInstallStore() to (re)create the marker rather than hand-creating the directory.","Ensure backup/sync tools include dotfiles."],"tags":["install-store","security","marker","removal-safety","cli"],"backgroundTag":null,"analyzedSha":"67001ec6eb96ae601aa27bc91d9b2415d665334a","analyzedAt":"2026-08-12T12:05:45.408Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}