{"record":{"id":"b7af47345126d9a1","repo":"strapi/strapi","slug":"invalid-route-config-error-message","errorCode":null,"errorMessage":"Invalid route config ${error.message}","messagePattern":"Invalid route config (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/core/core/src/services/server/routing.ts","lineNumber":79,"sourceCode":"      middlewares: yup\n        .array()\n        // FIXME: fixed in yup v1\n        .of(policyOrMiddlewareSchema as any)\n        .notRequired(),\n    })\n    .notRequired(),\n});\n\nconst validateRouteConfig = (routeConfig: Core.RouteInput) => {\n  try {\n    return routeSchema.validateSync(routeConfig, {\n      strict: true,\n      abortEarly: false,\n      stripUnknown: true,\n    });\n  } catch (error) {\n    if (error instanceof yup.ValidationError) {\n      throw new Error(`Invalid route config ${error.message}`);\n    }\n  }\n};\n\nconst createRouteManager = (strapi: Core.Strapi, opts: { type?: string } = {}) => {\n  const { type } = opts;\n\n  const composeEndpoint = createEndpointComposer(strapi);\n\n  const createRoute = (route: Core.RouteInput, router: Router) => {\n    validateRouteConfig(route);\n\n    // NOTE: the router type is used to tag controller actions and for authentication / authorization so we need to pass this info down to the route level\n    const routeWithInfo = Object.assign(route, {\n      info: {\n        ...route.info,\n        type: type ?? 'api',\n      },","sourceCodeStart":61,"sourceCodeEnd":97,"githubUrl":"https://github.com/strapi/strapi/blob/4a4101264d7098754df36e85fa629fd2f2349d8c/packages/core/core/src/services/server/routing.ts#L61-L97","documentation":"validateRouteConfig runs each route through a yup schema requiring method (one of GET/POST/PUT/PATCH/DELETE/ALL), path (string), and a handler (string, array, or function). Optional request/response/config shapes are also constrained. On any yup ValidationError the original message is wrapped and rethrown, failing route registration — typically at server boot or plugin load.","triggerScenarios":"Registering a custom route with a missing or invalid method/path/handler, a method not in the allowed enum (e.g. 'OPTIONS'), or a config.auth value that is neither false nor { scope: string[] }.","commonSituations":"Plugin route typos; copy-pasting a route and forgetting the handler; setting config.auth to a truthy non-object; using a lowercase method ('get').","solutions":["Ensure method is uppercase and in [GET, POST, PUT, PATCH, DELETE, ALL].","Provide a non-empty path string and a valid handler (string 'controller.action', array, or function).","For config.auth use either false or { scope: ['read'] }.","Read the embedded yup error.message in the thrown text for the specific failing field."],"exampleFix":"// before (throws — lowercase method, missing handler)\nmodule.exports = {\n  routes: [\n    { method: 'get', path: '/hello' },\n  ],\n};\n\n// after\nmodule.exports = {\n  routes: [\n    { method: 'GET', path: '/hello', handler: 'myController.find' },\n  ],\n};","handlingStrategy":"validation","validationCode":"const METHODS = ['GET','POST','PUT','PATCH','DELETE','ALL'];\nfunction validateRoute(r) {\n  if (!METHODS.includes(r.method)) throw new Error('Invalid method');\n  if (typeof r.path !== 'string' || !r.path) throw new Error('Invalid path');\n  if (!(typeof r.handler === 'string' || Array.isArray(r.handler) || typeof r.handler === 'function')) {\n    throw new Error('Invalid handler');\n  }\n}","typeGuard":"const isRouteInput = (r: unknown): boolean =>\n  typeof r === 'object' && r !== null &&\n  ['GET','POST','PUT','PATCH','DELETE','ALL'].includes((r as any).method) &&\n  typeof (r as any).path === 'string';","tryCatchPattern":null,"preventionTips":["Use uppercase HTTP methods in route definitions.","Always specify a handler for every route.","Validate plugin route files in unit tests."],"tags":["routes","server","yup","validation","config"],"backgroundTag":null,"analyzedSha":"4a4101264d7098754df36e85fa629fd2f2349d8c","analyzedAt":"2026-08-12T12:47:50.760Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}