Link to the code that reproduces this issue
https://github.com/vercel/next-config-fn-repro
To Reproduce
- Export an async function config from
next.config.mjs (the standard (phase, ctx) => config pattern used by plugins like withSentry, withWorkflow, etc.):
// next.config.mjs
function withExamplePlugin(nextConfig) {
return async (phase, { defaultConfig }) => {
return { ...nextConfig };
};
}
export default withExamplePlugin({
async rewrites() {
return [{ source: '/old', destination: '/new' }];
},
});
- Use
unstable_getResponseFromNextConfig to test rewrites/redirects:
import { unstable_getResponseFromNextConfig, getRewrittenUrl } from 'next/experimental/testing/server';
const nextConfig = (await import('./next.config.mjs')).default;
// typeof nextConfig === 'function'
const response = await unstable_getResponseFromNextConfig({ url: '/old', nextConfig });
getRewrittenUrl(response); // null — expected '/new'
Current vs. Expected behavior
Current: unstable_getResponseFromNextConfig passes the config directly to loadCustomRoutes, which accesses config.rewrites, config.redirects, etc. Since the config is a function (not an object), these properties are undefined and every route match returns null.
Expected: The utility should resolve function configs before passing them to loadCustomRoutes, the same way Next.js itself does at build time:
let resolved = nextConfig;
if (typeof resolved === 'function') {
resolved = await resolved('phase-production-build', { defaultConfig: {} });
}
Provide environment information
Operating System:
Platform: darwin
Arch: arm64
Next.js: 16.2.1-canary.24
Which area(s) are affected? (Select all that apply)
Testing utilities (next/experimental/testing/server)
Which stage(s) are affected? (Select all that apply)
Other (N/A — testing utility)
Additional context
The root cause is in next/dist/experimental/testing/server/config-testing-utils.js line 59:
const routes = await loadCustomRoutes(nextConfig);
loadCustomRoutes expects a plain config object. It immediately accesses config.assetPrefix, config.basePath, config.rewrites, etc.
This affects any project using Next.js config plugins that return async function wrappers — a common pattern across the ecosystem (@sentry/nextjs, @vercel/workflow, etc.).
Link to the code that reproduces this issue
https://github.com/vercel/next-config-fn-repro
To Reproduce
next.config.mjs(the standard(phase, ctx) => configpattern used by plugins likewithSentry,withWorkflow, etc.):unstable_getResponseFromNextConfigto test rewrites/redirects:Current vs. Expected behavior
Current:
unstable_getResponseFromNextConfigpasses the config directly toloadCustomRoutes, which accessesconfig.rewrites,config.redirects, etc. Since the config is a function (not an object), these properties areundefinedand every route match returnsnull.Expected: The utility should resolve function configs before passing them to
loadCustomRoutes, the same way Next.js itself does at build time:Provide environment information
Which area(s) are affected? (Select all that apply)
Testing utilities (
next/experimental/testing/server)Which stage(s) are affected? (Select all that apply)
Other (N/A — testing utility)
Additional context
The root cause is in
next/dist/experimental/testing/server/config-testing-utils.jsline 59:loadCustomRoutesexpects a plain config object. It immediately accessesconfig.assetPrefix,config.basePath,config.rewrites, etc.This affects any project using Next.js config plugins that return async function wrappers — a common pattern across the ecosystem (
@sentry/nextjs,@vercel/workflow, etc.).