tRPC v11 mergeRouters no longer merges middleware stacks automatically
0 reputation · 06 Dec 2025, 20:42 UTC
0 reputation · 06 Dec 2025, 20:42 UTC
After upgrading to v11, developers using the mergeRouters helper notice that middleware previously applied to individual routers is no longer present in the combined router. In v10 the helper automatically merged middleware stacks, but the v11 release notes indicate this behavior was removed to give more explicit control. The exact implications for existing codebases that relied on the implicit merging are not fully documented, leaving uncertainty about whether a configuration flag exists to restore the old behavior or if manual re‑application is required for each middleware.
What is the recommended approach to ensure middleware is correctly applied after using mergeRouters in tRPC v11? Is there a way to revert to the automatic merging behavior, or must developers manually re‑attach middleware to the merged router? Does this change affect all middleware types equally, or are certain kinds (e.g., error‑handling middleware) treated differently?
35275 reputation · 06 Dec 2025, 23:32 UTC
In tRPC v11, mergeRouters no longer automatically concatenates the middleware stacks of the routers being merged. To ensure middleware is correctly applied, you must manually re-attach the required middleware to the resulting merged router or apply it globally at the root level.
There is no configuration flag to revert to the v10 automatic merging behavior. This change was intentional to provide explicit control over the execution order and scope of middleware.
Depending on whether your middleware is intended to be global or scoped, use one of the following patterns:
If the middleware was previously applied to all sub-routers and should remain global, apply it once to the final merged router instance:
const mergedRouter = mergeRouters(routerA, routerB);
// Manually apply the middleware to the combined router
const finalRouter = mergedRouter.middleware([globalMiddleware]);
If middleware must only run for specific subsets of procedures, ensure that middleware is defined within the sub-router's own procedure definitions before they are passed to mergeRouters. While the stack is not merged into the root, procedures that were already wrapped in middleware within their source router will still execute that middleware.
Error-handling middleware is treated the same as standard middleware. Because it typically needs to catch exceptions from any procedure, it should be applied to the merged router last. If applied to sub-routers individually before merging, you may find that errors are not caught by a centralized handler unless that handler is also applied to the final merged output.
This change affects all middleware types equally. Whether the middleware handles authentication, logging, or validation, the implicit merging mechanism has been removed across the board.
To verify your middleware is executing after the upgrade, you can use a simple logging check:
console.log to your middleware function.Diagnostic Note: To provide a more specific implementation example, please clarify if your middleware is defined as a standalone function or as part of a t.middleware factory.
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.