nestjs/nest · critical · InvalidClassModuleException
"${metatype.name}" is decorated with @Injectable() and canno
Error message
"${metatype.name}" is decorated with @Injectable() and cannot appear in the "imports" array of a module. Please move "${metatype.name}" to the "providers" array of the importing module instead.
Scope [${scope}]
What it means
Before registering an import the scanner checks watermarks: a class carrying the @Injectable() watermark is a provider, not a module, and putting it in `imports` throws InvalidClassModuleException — '"X" is decorated with @Injectable() and cannot appear in the imports array of a module. Please move X to the providers array of the importing module instead.' DI can only inject providers from modules, so the array would be meaningless anyway.
Source
Thrown at packages/core/scanner.ts:199
return [moduleInstance].concat(registeredModuleRefs);
}
public async insertModule(
moduleDefinition: any,
scope: Type<unknown>[],
): Promise<
| {
moduleRef: Module;
inserted: boolean;
}
| undefined
> {
const moduleToAdd = this.isForwardReference(moduleDefinition)
? moduleDefinition.forwardRef()
: moduleDefinition;
if (this.isInjectable(moduleToAdd)) {
throw new InvalidClassModuleException(
moduleDefinition,
scope,
'provider',
);
}
if (this.isController(moduleToAdd)) {
throw new InvalidClassModuleException(
moduleDefinition,
scope,
'controller',
);
}
if (this.isExceptionFilter(moduleToAdd)) {
throw new InvalidClassModuleException(moduleDefinition, scope, 'filter');
}
return this.container.addModule(moduleToAdd, scope);
}View on GitHub (pinned to dd75d7bd8c)
Solutions
- Move the class from `imports` to the `providers` array of the same module.
- If the class depends on providers from other modules, keep it in `providers` and add the required modules to `imports`.
- Consume it elsewhere via export: `exports: [TheService]` on the owning module.
Example fix
// before
@Module({
imports: [CatsService], // wrong array
})
export class CatsModule {}
// after
@Module({
providers: [CatsService],
exports: [CatsService],
})
export class CatsModule {} Defensive patterns
Strategy: type-guard
Validate before calling
// Wiring test: nothing in imports arrays may be @Injectable()
import { INJECTABLE_WATERMARK } from '@nestjs/common/constants';
import 'reflect-metadata';
function assertNoInjectablesInImports(modules: Function[]) {
for (const m of modules) {
for (const imported of Reflect.getMetadata('imports', m) ?? []) {
const target = imported && 'forwardRef' in (imported as any) ? (imported as any).forwardRef() : imported;
if (typeof target === 'function' && Reflect.getMetadata(INJECTABLE_WATERMARK, target)) {
throw new Error(`${m.name}: @Injectable() ${target.name} belongs in providers, not imports`);
}
}
}
} Type guard
const isInjectableClass = (v: any): boolean =>
typeof v === 'function' && !!Reflect.getMetadata('__injectable__', v); Prevention
- Run the imports-array watermark scan above over all modules in a unit test.
- Keep arrays short and ordered (imports → controllers → providers) in every module to reduce mix-ups.
- Code-review rule: imports takes modules only; anything with @Injectable goes to providers.
When it happens
Trigger: Adding a service class to `imports` instead of `providers` (the two arrays are easy to confuse for newcomers); moving entries between arrays during refactoring and dropping them in the wrong one; importing a class decorated with a custom decorator that internally applies @Injectable().
Common situations: First NestJS projects wiring services; copying module templates and pasting service names into the wrong array; code reviews missing array mix-ups because TypeScript accepts any constructor in both arrays without strict typing.
Related errors
- Nest cannot export a provider/module that is not a part of t
- An invalid controller has been detected. "${className}" does
- Nest cannot create the ${parentModule.name} instance. The mo
- Nest cannot create the ${parentModule.name} instance. Receiv
- "${metatype.name}" is decorated with @Controller() and canno
AI-assisted analysis of nestjs/nest@dd75d7bd8c (2026-08-21).
Data as JSON: /api/errors/e56204ce369e6b0c.
Report an issue: GitHub.