{"record":{"id":"aa27403d89661eda","repo":"jackwener/OpenCLI","slug":"local-plugin-path-does-not-exist-localpath","errorCode":null,"errorMessage":"Local plugin path does not exist: ${localPath}","messagePattern":"Local plugin path does not exist: (.+?)","errorType":"validation","errorClass":"PluginError","httpStatus":null,"severity":"error","filePath":"src/plugin.ts","lineNumber":772,"sourceCode":"      upsertLockEntry(lock, pluginName, {\n        source: { kind: 'git', url: cloneUrl },\n        commitHash,\n      });\n      writeLockFile(lock);\n    }\n  });\n\n  return pluginName;\n}\n\n/**\n * Install a local plugin by creating a symlink.\n * Used for plugin development: the source directory is symlinked into\n * the plugins dir so changes are reflected immediately.\n */\nfunction installLocalPlugin(localPath: string, name: string): string {\n  if (!fs.existsSync(localPath)) {\n    throw new PluginError(`Local plugin path does not exist: ${localPath}`);\n  }\n\n  const stat = fs.statSync(localPath);\n  if (!stat.isDirectory()) {\n    throw new PluginError(`Local plugin path is not a directory: ${localPath}`);\n  }\n\n  const manifest = readPluginManifest(localPath);\n\n  if (manifest?.opencli && !checkCompatibility(manifest.opencli)) {\n    throw new PluginError(\n      `Plugin requires opencli ${manifest.opencli}, but current version is incompatible.`,\n      'Upgrade opencli to a compatible version.',\n    );\n  }\n\n  const pluginName = manifest?.name ?? name;\n  const targetDir = path.join(PLUGINS_DIR, pluginName);","sourceCodeStart":754,"sourceCodeEnd":790,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/src/plugin.ts#L754-L790","documentation":"installLocalPlugin symlinks a local directory into the plugins dir for plugin development. It throws a PluginError when the given path does not exist on disk (an adjacent check throws for non-directories). opencli throws this early so a clearly invalid path never gets symlinked or recorded in the lock file.","triggerScenarios":"installPlugin('/abs/path/to/plugin') or installPlugin('file:///abs/path/to/plugin') where the path doesn't exist: typo in path, directory deleted/renamed, path valid on another machine, or passing a relative path resolved against the wrong cwd.","commonSituations":"Plugin development folder moved or removed; wrong absolute path after switching machines/containers; passing a file instead of a directory; shell tab-completion used a stale path; Windows vs POSIX path style confusion.","solutions":["Verify the path exists: `ls <localPath>`; fix typos.","Pass an absolute path (relative paths are resolved against the process cwd, which may differ from your shell).","Rebuild/restore the plugin directory if it was deleted, or clone it again.","Ensure the path points to a directory containing the plugin, not a file or archive.","Use file:///absolute/path form if passing a file URL."],"exampleFix":"// before\ninstallPlugin('~/dev/my-plugin');   // ~ not expanded, doesn't exist\n// after\ninstallPlugin('/home/me/dev/my-plugin');","handlingStrategy":"validation","validationCode":"import * as fs from 'node:fs';\nimport * as path from 'node:path';\nconst localPath = path.resolve(expandHome(inputPath));\nif (!fs.existsSync(localPath)) throw new Error(`Path not found: ${localPath}`);\nif (!fs.statSync(localPath).isDirectory()) throw new Error(`Not a directory: ${localPath}`);","typeGuard":null,"tryCatchPattern":"try {\n  installPlugin(localPath);\n} catch (err) {\n  if (err instanceof PluginError && err.message.startsWith('Local plugin path does not exist')) {\n    // correct the path (resolve to absolute, expand ~) and retry\n  } else throw err;\n}","preventionTips":["Always pass absolute paths for local plugins; expand ~ and resolve relative paths yourself.","Confirm the directory exists with fs.existsSync before installing in scripts.","Point at the plugin directory, not a file or zip archive.","Re-verify dev-plugin paths after moving projects or switching machines/containers."],"tags":["filesystem","local-plugin","path-validation"],"backgroundTag":"path-does-not-exist","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}