strapi/strapi · error · Error

Middleware ${uid} has already been registered.

Error message

Middleware ${uid} has already been registered.

What it means

Thrown by `strapi.middleware.add(namespace, middlewares)` when a middleware name, once namespaced (via `addNamespace`), collides with an already-registered UID. Middlewares are stored in a map keyed by UID and the registry refuses to overwrite. The error fires during the per-key loop, so the first middleware in the batch that collides aborts the whole add.

Source

Thrown at packages/core/core/src/registries/middlewares.ts:50

    /**
     * Registers a middleware
     */
    set(uid: UID.Middleware, middleware: Core.Middleware) {
      middlewares[uid] = middleware;
      return this;
    },

    /**
     * Registers a map of middlewares for a specific namespace
     */
    add(namespace: string, rawMiddlewares: Record<string, Core.Middleware> = {}) {
      for (const middlewareName of Object.keys(rawMiddlewares)) {
        const middleware = rawMiddlewares[middlewareName];
        const uid = addNamespace(middlewareName, namespace) as UID.Middleware;

        if (has(uid, middlewares)) {
          throw new Error(`Middleware ${uid} has already been registered.`);
        }
        middlewares[uid] = middleware;
      }
    },

    /**
     * Wraps a middleware to extend it
     */
    extend(uid: UID.Middleware, extendFn: MiddlewareExtendFn) {
      const currentMiddleware = this.get(uid);

      if (!currentMiddleware) {
        throw new Error(`Middleware ${uid} doesn't exist`);
      }

      const newMiddleware = extendFn(currentMiddleware);
      middlewares[uid] = newMiddleware;

View on GitHub (pinned to 4a4101264d)

Solutions

  1. Rename the conflicting middleware in `server/src/middlewares/<name>.ts` so its namespaced UID is unique.
  2. Restart the dev server cleanly if you suspect HMR double-registration.
  3. Confirm the plugin isn't loaded twice via `plugins.config.js` + `package.json` deps.
  4. If you intended to override, use `strapi.middleware('<uid>').extend(fn)` instead of `add()`.

Example fix

// before — collides with core cors middleware
module.exports = {
  middlewares: { cors: { name: 'cors', handler: () => {} } },
};
// after — unique name, or use extend to override
strapi.middleware('plugin::myplugin.cors');
// or rename:
module.exports = {
  middlewares: { myCors: { name: 'myCors', handler: () => {} } },
};
Defensive patterns

Strategy: validation

Validate before calling

function addMiddlewareSafely(strapi, namespace, middlewares) {
  const existing = new Set(strapi.middleware.keys());
  for (const name of Object.keys(middlewares)) {
    const uid = `${namespace}::${name}`; // mirror addNamespace for known prefixes
    if (existing.has(uid)) {
      strapi.log.warn(`Skipping duplicate middleware ${uid}`);
      continue;
    }
  }
  strapi.middleware.add(namespace, middlewares);
}

Type guard

const isMiddlewareRegistered = (strapi, uid: string): boolean =>
  strapi.middleware.keys().includes(uid);

Try / catch

try {
  strapi.middleware.add(namespace, middlewares);
} catch (e) {
  if (!String(e.message).includes('has already been registered')) throw e;
}

Prevention

When it happens

Trigger: Two plugins defining a middleware with the same name. A plugin re-declaring a middleware Strapi core already registered (e.g. `global::cors`, `plugin::users-permissions.jwt`). Hot-reload during `develop` re-running `add()` against a non-cleared registry.

Common situations: Plugin named `users-permissions` re-registering `jwt`. Local plugin loaded twice (npm package + local path). Hot-reload double-registration. Forking a plugin and forgetting to rename the middleware file.

Related errors


AI-assisted analysis of strapi/strapi@4a4101264d (2026-08-12). Data as JSON: /api/errors/06e761f4da8247fb. Report an issue: GitHub.