{"record":{"id":"e5d4210de9ac2242","repo":"paperclipai/paperclip","slug":"plugin-manifest-id-routepath-conflictingrout","errorCode":null,"errorMessage":"Plugin ${manifest.id} routePath \"${conflictingRoute}\" conflicts with installed plugin ${plugin.pluginKey}","messagePattern":"Plugin (.+?) routePath \"(.+?)\" conflicts with installed plugin (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"server/src/services/plugin-loader.ts","lineNumber":1169,"sourceCode":"\n  async function assertPageRoutePathsAvailable(manifest: PaperclipPluginManifestV1): Promise<void> {\n    const requestedRoutePaths = getDeclaredPageRoutePaths(manifest);\n    if (requestedRoutePaths.length === 0) return;\n\n    const uniqueRequested = new Set(requestedRoutePaths);\n    if (uniqueRequested.size !== requestedRoutePaths.length) {\n      throw new Error(`Plugin ${manifest.id} declares duplicate page routePath values`);\n    }\n\n    const installedPlugins = await registry.listInstalled();\n    for (const plugin of installedPlugins) {\n      if (plugin.pluginKey === manifest.id) continue;\n      const installedManifest = plugin.manifestJson as PaperclipPluginManifestV1 | null;\n      if (!installedManifest) continue;\n      const installedRoutePaths = new Set(getDeclaredPageRoutePaths(installedManifest));\n      const conflictingRoute = requestedRoutePaths.find((routePath) => installedRoutePaths.has(routePath));\n      if (conflictingRoute) {\n        throw new Error(\n          `Plugin ${manifest.id} routePath \"${conflictingRoute}\" conflicts with installed plugin ${plugin.pluginKey}`,\n        );\n      }\n    }\n  }\n\n  // -------------------------------------------------------------------------\n  // Internal helpers\n  // -------------------------------------------------------------------------\n\n  /**\n   * Fetch a plugin from npm or local path, then parse and validate its manifest.\n   *\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.","sourceCodeStart":1151,"sourceCodeEnd":1187,"githubUrl":"https://github.com/paperclipai/paperclip/blob/120ae5428fa29bee300bcf806491cd4d965fbb7c/server/src/services/plugin-loader.ts#L1151-L1187","documentation":"Route-conflict guard: a routePath the manifest requests is already claimed by a different installed plugin. UI plugin pages occupy a global route namespace, so first-come wins; the conflicting manifest routePath is at fault.","triggerScenarios":"Thrown at server/src/services/plugin-loader.ts:1169 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":["Change the plugin's conflicting routePath to a unique value, or uninstall the other plugin that already owns that route."],"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-14T00:17:10.932Z"}