nextjs routing_error ai_generated true

Error: middleware must export a middleware or default function

ID: nextjs/middleware-export-error

Also available as: JSON · Markdown
94%Fix Rate
93%Confidence
80Evidence
2023-01-01First Seen

Version Compatibility

VersionStatusIntroducedDeprecatedNotes
14 active

Root Cause

Next.js requires the middleware file (middleware.ts or middleware.js) at the project root (next to app/ or pages/) to export a named function called 'middleware' or a default export that is a function. This error occurs when the file exists but lacks the correct export, has a syntax error preventing the export from being recognized, is placed in the wrong directory, or exports a non-function value. Common causes include placing middleware.ts inside the app/ directory instead of the project root, using module.exports instead of ES module exports, or having TypeScript type errors that prevent compilation. The fix is to ensure the correct file location and proper named export.

generic

Workarounds

  1. 95% success Create middleware.ts at the project root with the correct named export
    Create the file at {projectRoot}/middleware.ts (same level as package.json and the app/ directory): // middleware.ts
    import { NextResponse } from 'next/server';
    import type { NextRequest } from 'next/server';
    
    export function middleware(request: NextRequest) {
      // Your middleware logic
      return NextResponse.next();
    }
    
    // Optional: configure which routes middleware runs on
    export const config = {
      matcher: ['/dashboard/:path*', '/api/:path*'],
    };
    
    The function must be named 'middleware' (named export) or be the default export. Both work, but the named export is the documented convention
  2. 92% success Use the config.matcher export to control which routes trigger the middleware
    Export a config object alongside the middleware function to control execution: export const config = { matcher: ['/((?!_next/static|_next/image|favicon.ico|public).*)'] }; This prevents the middleware from running on static assets and internal Next.js routes. Common matchers: specific paths: ['/dashboard/:path*'], API routes: ['/api/:path*'], all except static: ['/((?!_next/static|_next/image|favicon.ico).*)'], combining: ['/dashboard/:path*', '/api/:path*', '/auth/:path*']. The matcher uses a path-to-regexp syntax
  3. 88% success Compose multiple middleware functions using a helper when you need modular middleware
    Since Next.js only supports a single middleware file, compose multiple middleware concerns: // middleware.ts
    import { NextResponse } from 'next/server';
    import type { NextRequest } from 'next/server';
    
    function withAuth(request: NextRequest): NextResponse | null {
      const token = request.cookies.get('token');
      if (!token && request.nextUrl.pathname.startsWith('/dashboard')) {
        return NextResponse.redirect(new URL('/login', request.url));
      }
      return null;
    }
    
    function withLocale(request: NextRequest): NextResponse | null {
      const locale = request.headers.get('accept-language')?.split(',')[0];
      if (locale && !request.nextUrl.pathname.startsWith(`/${locale}`)) {
        return NextResponse.rewrite(new URL(`/${locale}${request.nextUrl.pathname}`, request.url));
      }
      return null;
    }
    
    export function middleware(request: NextRequest) {
      const authResponse = withAuth(request);
      if (authResponse) return authResponse;
      const localeResponse = withLocale(request);
      if (localeResponse) return localeResponse;
      return NextResponse.next();
    }
    
    export const config = { matcher: ['/((?!_next/static|_next/image|favicon.ico).*)'] };

Dead Ends

Common approaches that don't work:

  1. Placing middleware.ts inside the app/ directory or pages/ directory 95% fail

    Next.js only recognizes the middleware file at the project root level (the same directory that contains app/ or pages/). Placing it inside app/middleware.ts or pages/middleware.ts causes it to be treated as a regular page or route, not as middleware. The middleware detection logic specifically looks for {projectRoot}/middleware.{ts,js}

  2. Using module.exports or CommonJS syntax in the middleware file 90% fail

    Next.js middleware runs in the Edge Runtime, which only supports ES modules. Using module.exports = function middleware() {} or exports.middleware = ... is not recognized. The middleware file must use ES module syntax with 'export function middleware()' or 'export default function()'. This is a common issue when copying patterns from older Node.js codebases or Express middleware

  3. Exporting an object or configuration instead of a function from middleware.ts 85% fail

    The middleware export must be a function that receives a NextRequest and returns a NextResponse or Response. Exporting a configuration object, a class, or a middleware factory without calling it will trigger this error. Even if using a higher-order function pattern like withAuth(handler), the final default export or named middleware export must be the resulting function, not the wrapper

Error Chain

Leads to:
Preceded by:
Frequently confused with: