Next.js Middleware Not Triggering: Common Issues and Solutions
Middleware in Next.js provides powerful capabilities for handling requests before they reach your routes, but getting it to work correctly can sometimes be challenging. This article covers the most common reasons why middleware might not trigger and provides practical solutions.
Understanding Middleware Placement
The correct location for your middleware file depends on your Next.js version and project structure:
For Projects Without src
Directory
Place middleware.js
or middleware.ts
in the root directory (same level as pages
or app
):
/myproject/
├── middleware.js
├── pages/ (or app/)
├── package.json
└── ...
For Projects With src
Directory
Place the middleware file in the src directory:
/myproject/
├── src/
│ └── middleware.js
├── pages/ (or app/)
├── package.json
└── ...
WARNING
Some Next.js versions (particularly 13-15) have had inconsistencies in middleware location requirements. If your middleware isn't working in one location, try the other.
Version-Specific Considerations
Next.js 12.x and Below
For versions earlier than 12.2.2, you need to:
- Name your file
_middleware.js
or_middleware.ts
- Place it inside the
pages
directory
Next.js 13.x and Above (App Router)
Recent versions support the App Router, which may require middleware in different locations:
- Try both root-level and
src/
locations - Some versions work better with middleware at
src/app/middleware.ts
Common Issues and Fixes
1. Incorrect File Naming
Ensure your file is named exactly:
middleware.js
(JavaScript)middleware.ts
(TypeScript)
DANGER
Even small typos like "middelware" instead of "middleware" will prevent it from working.
2. Custom Page Extensions
If you've configured custom page extensions in next.config.js
, your middleware might need to follow the same pattern:
// next.config.js
const nextConfig = {
pageExtensions: ["page.tsx", "api.ts", "page.jsx"],
};
// Your middleware should be named:
// middleware.page.ts or middleware.api.ts
3. Static Exports (output: 'export')
Middleware does not work with static exports:
// next.config.js
// ❌ This will disable middleware
const nextConfig = {
output: 'export',
};
// ✅ Remove output: 'export' for middleware to work
const nextConfig = {
// distDir: './dist', // Optional custom dist directory
};
4. Matcher Configuration Issues
Ensure your matcher configuration correctly targets the desired routes:
// middleware.js
export const config = {
// Match specific paths
matcher: ['/test', '/dashboard'],
// Or use a regex pattern
// matcher: ['/((?!api|_next/static|_next/image|favicon.ico).*)']
};
5. Using the Wrong Export
Make sure you're using the default export for your middleware function:
// ✅ Correct
export default function middleware(request) {
// Your middleware logic
}
// ❌ Incorrect (unless you have specific needs)
export function middleware(request) {
// This might not work in some configurations
}
Debugging Tips
Check the Right Console
Middleware logs appear in your server terminal, not the browser console. Always check where your server is running for middleware logging.
Verification Example
Use this simple middleware to test if it's working:
// middleware.js
import { NextResponse } from 'next/server';
export default function middleware(request) {
console.log('Middleware triggered for:', request.url);
return NextResponse.next();
}
export const config = {
matcher: '/test',
};
Testing Script
Create a simple test to verify middleware is working:
// test-middleware.js
const LOCALHOST_URL = "http://localhost:3000";
async function testMiddleware() {
try {
const response = await fetch(`${LOCALHOST_URL}/test`);
console.log('Response status:', response.status);
} catch (error) {
console.error('Test failed:', error);
}
}
testMiddleware();
Alternative to Middleware: Next.config.js Redirects
If you only need simple redirects, consider using next.config.js
instead:
// next.config.js
const nextConfig = {
async redirects() {
return [
{
permanent: true,
source: "/test",
destination: "/",
},
];
},
};
export default nextConfig;
Version Upgrade Recommendation
If you're using an older version of Next.js (especially version 12 or below), consider upgrading to benefit from improved middleware functionality and better documentation:
npm install next@latest react@latest react-dom@latest eslint-config-next@latest
Summary
Middleware not triggering in Next.js typically comes down to:
- Incorrect file location (root vs src directory)
- Wrong file naming (middleware.js vs _middleware.js)
- Configuration issues (pageExtensions, output: 'export')
- Version-specific requirements
By systematically checking these areas, you should be able to resolve most middleware triggering issues. When in doubt, consult the official Next.js middleware documentation for your specific version.