{"record":{"id":"6de80ed0853e0519","repo":"nestjs/nest","slug":"an-invalid-controller-has-been-detected-classn","errorCode":null,"errorMessage":"An invalid controller has been detected. \"${className}\" does not have the @Controller() decorator but it is being listed in the \"controllers\" array of some module.","messagePattern":"An invalid controller has been detected\\. \"(.+?)\" does not have the @Controller\\(\\) decorator but it is being listed in the \"controllers\" array of some module\\.","errorType":"exception","errorClass":"UnknownRequestMappingException","httpStatus":null,"severity":"critical","filePath":"packages/core/router/router-explorer.ts","lineNumber":131,"sourceCode":"  ) {\n    const { instance } = instanceWrapper;\n    const routerPaths = this.pathsExplorer.scanForPaths(instance);\n    this.applyPathsToRouterProxy(\n      httpAdapterRef,\n      routerPaths,\n      instanceWrapper,\n      moduleKey,\n      routePathMetadata,\n      host,\n      options,\n    );\n  }\n\n  public extractRouterPath(metatype: Type<Controller>): string[] {\n    const path = Reflect.getMetadata(PATH_METADATA, metatype);\n\n    if (isUndefined(path)) {\n      throw new UnknownRequestMappingException(metatype);\n    }\n    if (Array.isArray(path)) {\n      return path.map(p => addLeadingSlash(p));\n    }\n    return [addLeadingSlash(path)];\n  }\n\n  public applyPathsToRouterProxy<T extends HttpServer>(\n    router: T,\n    routeDefinitions: RouteDefinition[],\n    instanceWrapper: InstanceWrapper,\n    moduleKey: string,\n    routePathMetadata: RoutePathMetadata,\n    host: string | RegExp | Array<string | RegExp>,\n    options: RouteResolutionOptions = {},\n  ) {\n    (routeDefinitions || []).forEach(routeDefinition => {\n      const { version: methodVersion } = routeDefinition;","sourceCodeStart":113,"sourceCodeEnd":149,"githubUrl":"https://github.com/nestjs/nest/blob/dd75d7bd8c5e88048587e6768d36eb695f3e7a25/packages/core/router/router-explorer.ts#L113-L149","documentation":"While mapping controllers to routes the framework reads the path metadata that the `@Controller()` decorator writes onto the class. A class listed in a module's `controllers` array without that decorator has no PATH_METADATA, so NestJS throws UnknownRequestMappingException — 'An invalid controller has been detected. X does not have the @Controller() decorator but it is being listed in the controllers array of some module.'","triggerScenarios":"A plain class (service, DTO, utility) mistakenly added to a module's `controllers` array; the decorator was deleted or commented out during refactoring; the class is decorated by a custom pseudo-decorator that does not apply @Controller(); copy-paste of a controller file where the decorator line was not copied; decorators disabled in tsconfig (`experimentalDecorators: false`) so nothing gets written.","commonSituations":"Renaming a controller into a service but leaving it registered under controllers; large modules where arrays get long; upgrades to build tooling (swc/esbuild configs) that silently drop decorators when misconfigured; scaffolding mistakes.","solutions":["Decorate the class: `@Controller('path')` on the exact class listed in the module.","If the class is not meant to handle HTTP, move it to `providers` instead.","Ensure the correct class is imported (check for default vs named import mismatches) and the decorator is applied to the class, not exported separately.","Verify tsconfig: `experimentalDecorators: true` and, for emitted metadata, `emitDecoratorMetadata: true`."],"exampleFix":"// before\nexport class CatsController { // decorator missing\n  @Get() findAll() { return []; }\n}\n\n// after\nimport { Controller, Get } from '@nestjs/common';\n\n@Controller('cats')\nexport class CatsController {\n  @Get() findAll() { return []; }\n}","handlingStrategy":"type-guard","validationCode":"// Wiring test: every class in controllers arrays must carry controller metadata\nimport { CONTROLLER_WATERMARK, PATH_METADATA } from '@nestjs/common/constants';\nimport 'reflect-metadata';\n\nconst isNestController = (cls: any): boolean =>\n  typeof cls === 'function' &&\n  !!Reflect.getMetadata(CONTROLLER_WATERMARK, cls) &&\n  Reflect.getMetadata(PATH_METADATA, cls) !== undefined;\n\nfunction assertControllersValid(module: Function) {\n  for (const c of Reflect.getMetadata('controllers', module) ?? []) {\n    if (!isNestController(c)) throw new Error(`${module.name}: ${c?.name} is not decorated with @Controller()`);\n  }\n}","typeGuard":"const isNestController = (cls: unknown): cls is import('@nestjs/common').Type<any> =>\n  typeof cls === 'function' && Reflect.getMetadata('__controller__', cls) !== undefined;","tryCatchPattern":null,"preventionTips":["Run the controllers-array metadata check above in a wiring unit test for every module.","Keep controllers and providers in separate files so array mix-ups are caught by imports.","Confirm experimentalDecorators/emitDecoratorMetadata stay enabled after build-tool migrations."],"tags":["controller","decorator","routing","module-configuration","bootstrap"],"backgroundTag":"missing-controller-decorator","analyzedSha":"dd75d7bd8c5e88048587e6768d36eb695f3e7a25","analyzedAt":"2026-08-21T19:39:39.867Z","contentChangedAt":"2026-08-21T19:39:39.867Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}