medusajs/medusa · warning
No emitEvents_ method found on ${target.constructor.name}. N
Error message
No emitEvents_ method found on ${target.constructor.name}. No events emitted. To be able to use the @EmitEvents() you need to have the emitEvents_ method implemented in the class. What it means
The @EmitEvents() decorator runs the decorated method, then forwards the aggregated messages collected via the MedusaContext messageAggregator to the class's emitEvents_ method. If the service class has no emitEvents_ method, the collected events are simply dropped with this warning. The method is normally provided by extending MedusaService; hand-written services that add the decorator without the base class lose events.
Source
Thrown at packages/core/utils/src/modules-sdk/decorators/emit-events.ts:32
return function (
target: any,
propertyKey: string | symbol,
descriptor: any
): void {
InjectIntoContext({
messageAggregator: () => new MessageAggregator(),
})(target, propertyKey, descriptor)
const original = descriptor.value
descriptor.value = async function (...args: any[]) {
const result = await original.apply(this, args)
if (!target.emitEvents_) {
const logger = Object.keys(this.__container__ ?? {}).includes("logger")
? this.__container__.logger
: console
logger.warn(
`No emitEvents_ method found on ${target.constructor.name}. No events emitted. To be able to use the @EmitEvents() you need to have the emitEvents_ method implemented in the class.`
)
}
const argIndex = target.MedusaContextIndex_[propertyKey]
const aggregator = args[argIndex].messageAggregator as MessageAggregator
if (aggregator.count() > 0) {
await target.emitEvents_.apply(this, [aggregator.getMessages(options)])
aggregator.clearMessages()
}
return result
}
}
}
View on GitHub (pinned to 5e06e544a2)
Solutions
- Make the class extend MedusaService<...>(models), which implements emitEvents_
- Or implement emitEvents_ manually: protected async emitEvents_(context: Context) { ... flush context.messageAggregator messages ... }
- Remove @EmitEvents() from methods of classes that should not emit domain events
Example fix
// before
export class MyService { // no base class
@EmitEvents()
async createThing(...) {}
}
// after
export class MyService extends MedusaService<{ Thing: { dto: ThingDTO } }>({ Thing }) {
@EmitEvents()
async createThing(...) {}
} Defensive patterns
Strategy: type-guard
Validate before calling
if (typeof (service as any).emitEvents_ !== "function") {
console.warn("@EmitEvents used on class without emitEvents_")
} Type guard
const canEmitEvents = (s: object): boolean =>
typeof (s as { emitEvents_?: unknown }).emitEvents_ === "function" Prevention
- Extend MedusaService for any class using @EmitEvents
- Don't copy decorators onto hand-written services without emitEvents_
- In tests, mock emitEvents_ on fake services
When it happens
Trigger: Adding @EmitEvents() to a method of a class that does not extend MedusaService (or otherwise does not define an async emitEvents_(context) method). Medusa module services like ApiKeyModuleService/CartModuleService etc. get it from the base class, so this only fires for custom or mis-wired classes.
Common situations: Building a custom service that mimics Medusa module services and copying the decorator; refactoring a service to no longer extend MedusaService while keeping decorators; mocking services in tests (FakeService) that apply the decorator without the base implementation.
Related errors
- Unable to load resources for module ${modulePath} automagica
- Primary keys are not defined by the module ${keyName}. Setti
AI-assisted analysis of medusajs/medusa@5e06e544a2 (2026-08-27).
Data as JSON: /api/errors/eebabc3e3fd3b9a0.
Report an issue: GitHub.