{"record":{"id":"902126cdc83e2d7a","repo":"YMFE/yapi","slug":"plugin-route-path-conflict-please-try-rename-the-902126","errorCode":null,"errorMessage":"Plugin Route path conflict, please try rename the path","messagePattern":"Plugin Route path conflict, please try rename the path","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"server/websocket.js","lineNumber":18,"sourceCode":"const koaRouter = require('koa-router');\nconst interfaceController = require('./controllers/interface.js');\nconst yapi = require('./yapi.js');\n\nconst router = koaRouter();\nconst { createAction } = require(\"./utils/commons.js\")\n\nlet pluginsRouterPath = [];\n\n\nfunction addPluginRouter(config) {\n  if (!config.path || !config.controller || !config.action) {\n    throw new Error('Plugin Route config Error');\n  }\n  let method = config.method || 'GET';\n  let routerPath = '/ws_plugin/' + config.path;\n  if (pluginsRouterPath.indexOf(routerPath) > -1) {\n    throw new Error('Plugin Route path conflict, please try rename the path')\n  }\n  pluginsRouterPath.push(routerPath);\n  createAction(router, \"/api\", config.controller, config.action, routerPath, method, true);\n}\n\n\nfunction websocket(app) {\n  createAction(router, \"/api\", interfaceController, \"solveConflict\", \"/interface/solve_conflict\", \"get\")\n\n  yapi.emitHookSync('add_ws_router', addPluginRouter);\n\n\n  app.ws.use(router.routes())\n  app.ws.use(router.allowedMethods());\n  app.ws.use(function (ctx, next) {\n    return ctx.websocket.send(JSON.stringify({\n      errcode: 404,\n      errmsg: 'No Fount.'","sourceCodeStart":1,"sourceCodeEnd":36,"githubUrl":"https://github.com/YMFE/yapi/blob/59bade3a8a43e7db077d38a4b0c7c584f30ddf8c/server/websocket.js#L1-L36","documentation":"addPluginRouter() in server/websocket.js throws this when two plugin routes resolve to the same '/ws_plugin/<path>' routePath. routes are tracked in the pluginsRouterPath array and duplicates are rejected to avoid route shadowing.","triggerScenarios":"Two plugins (or one plugin registering twice) define routes with the same path value, e.g. both register path 'open' so '/ws_plugin/open' collides.","commonSituations":"Installing two plugins that use the same default route path; enabling the same plugin twice in config; hot-reload re-running plugin registration without clearing pluginsRouterPath; plugin path left as default placeholder.","solutions":["Rename the path in one of the plugins so each '/ws_plugin/*' path is unique","Check the plugin list in config for duplicate plugin entries and remove one","If caused by hot-reload, guard registration so each plugin registers once per process","Upgrade the conflicting plugin to a version that namespaces its ws routes"],"exampleFix":"// before (plugin B)\naddPluginRouter({ path: 'status', controller: ctrlB, action: 'get' }); // collides with plugin A\n// after (plugin B)\naddPluginRouter({ path: 'pluginB/status', controller: ctrlB, action: 'get' });","handlingStrategy":"validation","validationCode":"const seen = new Set();\nconfigs.forEach(c => {\n  const p = '/ws_plugin/' + c.path;\n  if (seen.has(p)) throw new Error(`duplicate ws plugin route: ${p}`);\n  seen.add(p);\n});","typeGuard":null,"tryCatchPattern":"try {\n  addPluginRouter(config);\n} catch (e) {\n  if (/path conflict/.test(e.message)) {\n    console.error(`ws route '${config.path}' already registered by another plugin`);\n  } else throw e;\n}","preventionTips":["Namespace plugin ws paths with the plugin name (e.g. 'myplugin/status')","Avoid enabling the same plugin twice in the config","If the loader can run twice, track registered routes outside the reload cycle"],"tags":["plugin","websocket","route-conflict"],"backgroundTag":"route-conflict","analyzedSha":"59bade3a8a43e7db077d38a4b0c7c584f30ddf8c","analyzedAt":"2026-08-29T08:45:22.203Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}