{"record":{"id":"7caf1710c2efabb3","repo":"mastra-ai/mastra","slug":"custom-api-route-route-path-must-not-start-wi","errorCode":null,"errorMessage":"Custom API route \"${route.path}\" must not start with \"${prefix}\" — that path is reserved for built-in Mastra routes. Choose a different path (e.g. \"${route.path.replace(prefix, '/custom')}\").","messagePattern":"Custom API route \"(.+?)\" must not start with \"(.+?)\" — that path is reserved for built-in Mastra routes\\. Choose a different path \\(e\\.g\\. \"(.+?)\"\\)\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/server/src/server/server-adapter/index.ts","lineNumber":1018,"sourceCode":"    const schemaRoutes = routes.filter(isSchemaApiRoute);\n    for (const route of schemaRoutes) {\n      await this.registerRoute(this.app, route as unknown as ServerRoute, { prefix: '' });\n    }\n\n    return routes.filter((route): route is HonoCustomApiRoute => !isSchemaApiRoute(route));\n  }\n\n  /**\n   * Validates that no custom route path collides with the built-in route prefix.\n   * Throws if any route path starts with the server's `apiPrefix`.\n   */\n  protected validateCustomRoutePaths(routes: ApiRoute[]): void {\n    const prefix = this.prefix ?? '';\n    if (!prefix) return;\n    for (const route of routes) {\n      if (route._mastraInternal) continue;\n      if (route.path.startsWith(`${prefix}/`) || route.path === prefix) {\n        throw new Error(\n          `Custom API route \"${route.path}\" must not start with \"${prefix}\" — ` +\n            `that path is reserved for built-in Mastra routes. ` +\n            `Choose a different path (e.g. \"${route.path.replace(prefix, '/custom')}\").`,\n        );\n      }\n    }\n  }\n\n  /**\n   * Creates an internal Hono sub-app with all custom API routes registered.\n   * Stores the handler on this instance for use by handleCustomRouteRequest().\n   * Returns true if custom routes were found and registered.\n   */\n  protected async buildCustomRouteHandler(routes: HonoCustomApiRoute[]): Promise<boolean> {\n    if (routes.length === 0) return false;\n\n    const NOT_FOUND_HEADER = 'x-mastra-custom-route-not-found';\n    const mastra = this.mastra;","sourceCodeStart":1000,"sourceCodeEnd":1036,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/packages/server/src/server/server-adapter/index.ts#L1000-L1036","documentation":"Custom user-defined API routes may not occupy the same path prefix as the built-in Mastra server routes (the configured prefix, default '/api'). This check at server startup prevents custom handlers from shadowing or conflicting with internal routes. It throws with the offending path and a suggested alternative.","triggerScenarios":"Calling registerApiRoute (or passing routes to the server config) with a path equal to or nested under the server prefix, e.g. '/api/agents' when prefix is '/api', unless the route is marked _mastraInternal.","commonSituations":"Defining a custom proxy for built-in endpoints and accidentally reusing '/api/...'; changing the server 'prefix' config so existing custom routes now collide; copy-pasting built-in route paths into custom route definitions.","solutions":["Rename the custom route path so it does not start with the prefix (e.g. '/custom/api/agents' or '/my-api/...')","If you truly intend to override a built-in route, use the documented built-in-route override mechanism instead of a custom route","Check the server 'prefix' option — a changed prefix may now include routes that previously did not collide"],"exampleFix":"// before\nregisterApiRoute('/api/agents/custom', { method: 'POST', handler })\n// after\nregisterApiRoute('/custom/agents/custom', { method: 'POST', handler })","handlingStrategy":"validation","validationCode":"const prefix = '/api';\nconst bad = routes.filter(r => !r._mastraInternal && (r.path === prefix || r.path.startsWith(prefix + '/')));\nif (bad.length) throw new Error('Reserved prefix collision: ' + bad.map(r => r.path));","typeGuard":"const collidesWithPrefix = (p: string, prefix: string): boolean =>\n  p === prefix || p.startsWith(`${prefix}/`);","tryCatchPattern":null,"preventionTips":["Prefix custom routes with a non-reserved namespace","Test server boot in CI to catch collisions at deploy time","Document the reserved prefix for the team"],"tags":["routes","configuration","path-conflict"],"backgroundTag":"reserved-route-path-conflict","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T08:17:16.595Z"}