{"record":{"id":"6cb33bc46be31740","repo":"paperclipai/paperclip","slug":"either-packagename-or-localpath-must-be-provided","errorCode":null,"errorMessage":"Either packageName or localPath must be provided","messagePattern":"Either packageName or localPath must be provided","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"server/src/services/plugin-loader.ts","lineNumber":1200,"sourceCode":"   *\n   * This internal helper encapsulates the core plugin retrieval and validation\n   * logic used by both install and upgrade operations. It handles:\n   * 1. Resolving the package from npm or local filesystem.\n   * 2. Installing the package via npm if necessary.\n   * 3. Reading and parsing the plugin manifest.\n   * 4. Validating API version compatibility.\n   * 5. Validating manifest capabilities.\n   *\n   * @param installOptions - Options specifying the package to fetch.\n   * @returns A `DiscoveredPlugin` object containing the validated manifest.\n   */\n  async function fetchAndValidate(\n    installOptions: PluginInstallOptions,\n  ): Promise<DiscoveredPlugin> {\n    const { packageName, localPath, version, installDir } = installOptions;\n\n    if (!packageName && !localPath) {\n      throw new Error(\"Either packageName or localPath must be provided\");\n    }\n\n    const targetInstallDir = installDir ?? localPluginDir;\n\n    // Step 1 & 2: Resolve and install package\n    let resolvedPackagePath: string;\n    let resolvedPackageName: string;\n\n    if (localPath) {\n      // Local path install — validate the directory exists\n      const absLocalPath = path.resolve(localPath);\n      if (!existsSync(absLocalPath)) {\n        throw new Error(`Local plugin path does not exist: ${absLocalPath}`);\n      }\n      resolvedPackagePath = absLocalPath;\n      const pkgJson = await readPackageJson(absLocalPath);\n      resolvedPackageName =\n        typeof pkgJson?.[\"name\"] === \"string\"","sourceCodeStart":1182,"sourceCodeEnd":1218,"githubUrl":"https://github.com/paperclipai/paperclip/blob/120ae5428fa29bee300bcf806491cd4d965fbb7c/server/src/services/plugin-loader.ts#L1182-L1218","documentation":"Input guard in fetchAndValidate: neither packageName nor localPath was provided, so there is nothing to resolve or install. The caller must supply exactly one package source; the empty install options are at fault.","triggerScenarios":"Thrown at server/src/services/plugin-loader.ts:1200 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":["Provide either packageName (npm) or localPath (filesystem) when installing the plugin; exactly one source is required."],"exampleFix":null,"handlingStrategy":"validation","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"analyzedSha":"120ae5428fa29bee300bcf806491cd4d965fbb7c","analyzedAt":"2026-08-18T22:49:45.177Z","contentChangedAt":"2026-08-18T22:49:45.177Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}