medusajs/medusa · error · MedusaError

Trying to register a fulfillment provider without an identif

Error message

Trying to register a fulfillment provider without an identifier.

What it means

Static validator used when registering fulfillment provider plugin classes. A provider class must declare a static `identifier` property; without it the registration key (`identifier_optionName`) cannot be built and an INVALID_ARGUMENT error is thrown.

Source

Thrown at packages/modules/fulfillment/src/services/fulfillment-provider.ts:51

) {
  protected readonly fulfillmentProviderRepository_: DAL.RepositoryService
  #logger: Logger

  constructor(container: InjectedDependencies) {
    super(container)
    this.fulfillmentProviderRepository_ =
      container.fulfillmentProviderRepository
    this.#logger = container["logger"]
      ? container.logger
      : (console as unknown as Logger)
  }

  static getRegistrationIdentifier(
    providerClass: Constructor<IFulfillmentProvider>,
    optionName?: string
  ) {
    if (!(providerClass as any).identifier) {
      throw new MedusaError(
        MedusaError.Types.INVALID_ARGUMENT,
        `Trying to register a fulfillment provider without an identifier.`
      )
    }
    return `${(providerClass as any).identifier}_${optionName}`
  }

  protected retrieveProviderRegistration(
    providerId: string
  ): FulfillmentTypes.IFulfillmentProvider {
    try {
      return this.__container__[`fp_${providerId}`]
    } catch (err) {
      if (err.name === "AwilixResolutionError") {
        const errMessage = `
Unable to retrieve the fulfillment provider with id: ${providerId}
Please make sure that the provider is registered in the container and it is configured correctly in your project configuration file.`

View on GitHub (pinned to 5e06e544a2)

Solutions

  1. Add `static identifier = "..."` to the provider class
  2. If it also has options, also set `static identifier` plus option registration via provider loader conventions
  3. Ensure you export the class itself, not an instance

Example fix

// before
class MyFulfillmentProvider extends AbstractFulfillmentService { ... }
// after
class MyFulfillmentProvider extends AbstractFulfillmentService {
  static identifier = 'my-fulfillment'
  // ...
}
Defensive patterns

Strategy: validation

Validate before calling

import { FulfillmentProvider } from '@medusajs/fulfillment'
// before registration
if (!(MyProvider as any).identifier) throw new Error('Provider missing static identifier')

Type guard

const hasIdentifier = (cls: any): boolean => typeof cls?.identifier === 'string' && cls.identifier.length > 0

Prevention

When it happens

Trigger: Registering a custom fulfillment provider class that lacks `static identifier = 'my-provider'`, or where identifier is set only on instances/prototype instead of the class.

Common situations: Writing a first custom provider and forgetting the static field; refactoring a provider from an object to a class and losing the static.

Related errors


AI-assisted analysis of medusajs/medusa@5e06e544a2 (2026-08-27). Data as JSON: /api/errors/1ce39bce3f26703a. Report an issue: GitHub.