How to Fix Could Not Parse Module [project]/proxy.ts in Next.js

Introduction

Could Not Parse Module [project]/proxy.ts

The error “Could Not Parse Module [project]/proxy.ts” can be confusing when you are working with a Next.js application. The message points to proxy.ts, but it does not always explain what is wrong inside the file. In most cases, Next.js cannot read or compile the file because of invalid TypeScript syntax, an incorrect export, an unsupported import, or an incorrect file location.

The problem is also more common when upgrading a project. In current Next.js versions, the older middleware.ts file convention has been renamed to proxy.ts. The logic is similar, but the function and file names need to match the new convention. Next.js runs Proxy code before a request is completed, so it is often used for authentication checks, redirects, rewrites, logging, and request headers. See the official Next.js Proxy documentation for the complete API reference.

This guide explains the most common causes of Could Not Parse Module [project]/proxy.ts and shows practical fixes that beginners can follow.

What Does the Error Mean?

When Next.js says it could not parse proxy.ts, it means the compiler or bundler could not understand the module. The file may contain a syntax error, an invalid export, a misplaced bracket, or code that does not match the Next.js Proxy convention.

The error can happen during next dev, while the development server is starting, or during next build. The exact terminal message may identify a line number. Always check that line first, but also inspect the complete file because an error on an earlier line can make a later line look incorrect.

Starting with Next.js 16, Middleware is called Proxy. The official migration guide explains that the file should change from middleware.ts to proxy.ts, and the exported function should change from middleware to proxy. Read the official Middleware-to-Proxy migration guide when upgrading an existing project.

Step 1: Use a Valid proxy.ts File

Start by replacing the file temporarily with a small, valid example. This helps you determine whether the issue is with the file structure or with your custom logic.

import type { NextRequest } from 'next/server'
import { NextResponse } from 'next/server'

export function proxy(request: NextRequest) {
  return NextResponse.next()
}Code language: JavaScript (javascript)

This example does three simple things:

  1. Imports the NextRequest type.
  2. Imports NextResponse from next/server.
  3. Exports one function named proxy.

If this file works, the original problem is probably in your previous code. Add your imports and logic again one part at a time. If the minimal file still fails, continue with the file-location and version checks below.

Step 2: Check the File Location

The proxy.ts file must be in the project root, or inside the src folder when your project uses src. It should be at the same level as the app or pages directory.

Correct root structure:

my-next-app/
├── app/
├── public/
├── proxy.ts
├── package.json
├── tsconfig.json
└── next.config.tsCode language: PHP (php)

Correct src structure:

my-next-app/
├── src/
│   ├── app/
│   └── proxy.ts
├── public/
├── package.json
└── tsconfig.jsonCode language: PHP (php)

Do not place the file inside app/dashboard/proxy.ts, pages/admin/proxy.ts, or another nested route folder. Next.js supports one root Proxy file. If you need different behavior for different routes, keep one proxy.ts file and use conditions or a matcher.

import type { NextRequest } from 'next/server'

export function proxy(request: NextRequest) {
  const path = request.nextUrl.pathname

  if (path.startsWith('/dashboard')) {
    // Dashboard-specific logic
  }

  if (path.startsWith('/admin')) {
    // Admin-specific logic
  }
}Code language: JavaScript (javascript)

The Next.js nested Proxy error documentation explains why multiple nested Proxy files are not supported.

Step 3: Check the Export Name

One of the most common upgrade mistakes is renaming the file but not renaming the function.

This may be left over from an older Middleware implementation:

import type { NextRequest } from 'next/server'
import { NextResponse } from 'next/server'

export function middleware(request: NextRequest) {
  return NextResponse.next()
}Code language: JavaScript (javascript)

For the current Proxy convention, use this:

import type { NextRequest } from 'next/server'
import { NextResponse } from 'next/server'

export function proxy(request: NextRequest) {
  return NextResponse.next()
}Code language: JavaScript (javascript)

You can also use a default export:

import type { NextRequest } from 'next/server'
import { NextResponse } from 'next/server'

export default function proxy(request: NextRequest) {
  return NextResponse.next()
}Code language: JavaScript (javascript)

Use one Proxy function in the file. Do not export both a named Proxy function and a default Proxy function. The official Proxy reference supports a default export or a named proxy function, with an optional config export.

Step 4: Fix TypeScript Syntax Errors

The message Could Not Parse Module [project]/proxy.ts often comes from a basic syntax problem. Look for the following issues:

  • A missing closing brace }
  • A missing closing parenthesis )
  • A missing quote around a string
  • A missing comma in an object
  • JSX inside a .ts file instead of a .tsx file
  • An unfinished if statement
  • Incorrect TypeScript type syntax

For example, this code is invalid because the if statement is not closed:

export function proxy(request: NextRequest) {
  if (request.nextUrl.pathname.startsWith('/admin') {
    return NextResponse.redirect(new URL('/login', request.url))
  }

  return NextResponse.next()
}Code language: JavaScript (javascript)

The closing parenthesis is missing after '/admin'. The corrected version is:

export function proxy(request: NextRequest) {
  if (request.nextUrl.pathname.startsWith('/admin')) {
    return NextResponse.redirect(new URL('/login', request.url))
  }

  return NextResponse.next()
}Code language: JavaScript (javascript)

Run TypeScript directly to find errors faster:

npx tsc --noEmit

Your editor may also underline the exact location of the syntax error. Fix the first error shown before working on later errors.

Step 5: Use Correct Redirect and Rewrite URLs

Redirects and rewrites inside Proxy should use valid absolute URLs. A common mistake is passing a relative string directly to NextResponse.redirect or NextResponse.rewrite.

Avoid this pattern:

return NextResponse.redirect('/login')Code language: JavaScript (javascript)

Use the request URL as the base instead:

return NextResponse.redirect(new URL('/login', request.url))Code language: JavaScript (javascript)

A complete authentication example looks like this:

import type { NextRequest } from 'next/server'
import { NextResponse } from 'next/server'

export function proxy(request: NextRequest) {
  const token = request.cookies.get('token')?.value
  const pathname = request.nextUrl.pathname

  if (pathname.startsWith('/dashboard') && !token) {
    const loginUrl = new URL('/login', request.url)
    loginUrl.searchParams.set('from', pathname)

    return NextResponse.redirect(loginUrl)
  }

  return NextResponse.next()
}

export const config = {
  matcher: ['/dashboard/:path*'],
}Code language: JavaScript (javascript)

The Next.js Proxy relative URL guide recommends creating an absolute URL for redirects and rewrites. For complex applications, cloning request.nextUrl can also preserve settings such as basePath and locale configuration.

Step 6: Check the matcher Configuration

The matcher configuration controls which paths run through Proxy. Keep matcher values as static strings or arrays so Next.js can analyze them during the build.

Good example:

export const config = {
  matcher: ['/dashboard/:path*', '/profile/:path*'],
}Code language: JavaScript (javascript)

Problematic example:

const protectedPath = '/dashboard/:path*'

export const config = {
  matcher: protectedPath,
}Code language: JavaScript (javascript)

Dynamic matcher values may be ignored because Next.js needs to analyze them statically. Also remember that Proxy without a matcher can run on many requests, including static files and image assets. A redirect or authentication check that accidentally affects CSS, JavaScript, or images can make the entire application appear broken.

Step 7: Review Imports and Runtime Compatibility

Proxy code runs outside the normal React component environment. Avoid importing browser-only values such as window or document, and be careful with server-only packages that are not supported in the Proxy runtime.

Do not write this at the top level:

const currentPath = window.location.pathnameCode language: JavaScript (javascript)

Use the request object instead:

export function proxy(request: NextRequest) {
  const currentPath = request.nextUrl.pathname
  return NextResponse.next()
}Code language: JavaScript (javascript)

Also avoid putting database queries, large business rules, or heavy dependencies in Proxy. Use Proxy for an early request decision, then perform secure data checks in your server-side data layer or route handler. This keeps the Proxy file small and reduces build and runtime problems.

Step 8: Check Your Next.js Version and Migrate Carefully

Run this command to see the installed version:

npm list nextCode language: PHP (php)

If your project uses an older version, it may still expect middleware.ts. If you are upgrading to a version that uses the Proxy convention, migrate both the filename and function name together.

npx @next/codemod@canary middleware-to-proxy .Code language: CSS (css)

After migration, inspect the file manually. Codemods are useful, but you should still check custom imports, matchers, redirects, and authentication logic.

Step 9: Clear the Development Cache and Rebuild

Sometimes the source code is fixed but the development cache still contains an old compilation result. Stop the development server, remove the .next directory, and start it again.

On macOS or Linux:

rm -rf .next
npm run devCode language: CSS (css)

On Windows PowerShell:

Remove-Item -Recurse -Force .next
npm run devCode language: CSS (css)

Then test a production build:

npm run build
npm run start

Do not delete node_modules immediately. First check syntax, exports, file location, imports, and the Next.js version. Reinstall dependencies only when the package installation itself appears damaged.

Best Practices for proxy.ts

Follow these practices to avoid the error in future projects:

  1. Keep one small root-level proxy.ts file.
  2. Export one named proxy function or one default function.
  3. Use NextRequest and NextResponse from next/server.
  4. Keep matcher values static.
  5. Use absolute URLs for redirects and rewrites.
  6. Avoid browser APIs such as window and document.
  7. Protect static assets from unnecessary authentication logic.
  8. Run npx tsc --noEmit before committing changes.
  9. Test both npm run dev and npm run build.
  10. Keep sensitive authorization decisions in secure server-side code, not only in a client-side check.

Common Mistakes

Keeping middleware as the exported function

When using proxy.ts, rename the function to proxy unless you deliberately use the supported default export form.

Creating more than one Proxy file

Do not create separate Proxy files inside multiple route folders. Combine the logic in the root proxy.ts and use matcher values or pathname conditions.

Returning nothing from some branches

Make sure every request reaches a valid response, usually NextResponse.next():

export function proxy(request: NextRequest) {
  if (request.nextUrl.pathname === '/old-page') {
    return NextResponse.redirect(new URL('/new-page', request.url))
  }

  return NextResponse.next()
}Code language: JavaScript (javascript)

Copying all request headers

Forwarding every header can expose sensitive information or affect framework behavior. If you need to forward headers, create a small allow-list of safe headers. The NextResponse documentation explains the difference between forwarding request headers and sending response headers.

Mixing JSX with TypeScript

proxy.ts is not a React UI component. Keep JSX out of this file. If a UI file contains JSX, use the .tsx extension instead.

Quick Troubleshooting Checklist

Before searching for a more complex solution, check the following:

  • Is the file named exactly proxy.ts with the correct lowercase spelling?
  • Is it in the project root or the correct src location?
  • Does it export proxy or a supported default function?
  • Is there only one Proxy file?
  • Are all braces, parentheses, commas, and quotes closed?
  • Are imports coming from valid packages?
  • Are redirects and rewrites using absolute URLs?
  • Are matcher values static?
  • Are you using the correct convention for your installed Next.js version?
  • Does npx tsc --noEmit pass?
  • Does npm run build pass after clearing .next?

Leave a Reply

Your email address will not be published. Required fields are marked *