How Do I Fix the ‘Module Not Found Can’t Resolve react/jsx-runtime Error in Next.js

I was working on a Next.js + TypeScript project when I ran into a strange and frustrating error during build:

Module not found: Can't resolve 'react/jsx-runtime'

At first, I was confused I already had react and react-dom installed. So why was Next.js acting like React didn’t exist.

Turns out, the problem wasn’t React itself but how it was being resolved under the hood. I’ll walk you through:

My Original Setup

Here’s my original package.json:

{
  "name": "frontend",
  "version": "1.0.0",
  "private": true,
  "scripts": {
    "dev": "dotenv -e ../../.env -- sh -c 'next dev --port $FE_SERVER_PORT'",
    "build": "next build"
  },
  "dependencies": {
    "react": "^19.1.1",
    "react-dom": "^19.1.1"
  },
  "devDependencies": {
    "@types/react": "^19.1.11",
    "@types/react-dom": "^19.1.8"
  },
  "overrides": {
    "react": "$react"
  }
}

And here’s my tsconfig.json:

{
  "compilerOptions": {
    "jsx": "preserve",
    "jsxImportSource": "react",
    "module": "commonjs",
    "target": "ES2023",
    "esModuleInterop": true,
    "strict": true,
    "skipLibCheck": true
  }
}

Everything looked fine but the problem was hiding in plain sight.

Why This Error Happens

Here’s what I learned:

  • React 17 and above introduced a new internal package called react/jsx-runtime, which Next.js relies on for compiling JSX/TSX.
  • If Webpack (used internally by Next.js) can’t resolve this file, it assumes React is missing, even when installed.
  • In my case, the issue came from two major suspects:
CauseExplanation
Wrong React versionReact 19 is still experimental in some Next.js setups
Alias overridesMy "overrides" and Webpack aliasing unintentionally blocked proper module resolution

How I Fixed It

Downgraded to Stable React 18

npm install react@18 react-dom@18

Removed Overrides in package.json

"overrides": {
-  "react": "$react"
}

Cleaned Up Aliases (in next.config.ts)

If you’ve added aliases like this remove them unless absolutely necessary:

config.resolve.alias = {
  ...config.resolve.alias,
- 'react': require.resolve('react'),
- 'react-dom': require.resolve('react-dom')
}

Let Next.js handle resolving React automatically — it’s smarter than we think!

Clean Install

rm -rf node_modules .next package-lock.json
npm install
npm run dev

At this point no more jsx-runtime error!

Practice Component to Confirm the Fix

To be sure everything was working, I wrote a tiny test component:

// components/Hello.tsx
import React from "react";

export default function Hello({ name }: { name: string }) {
  return <h1>Hello, {name}! </h1>;
}

And used it inside my homepage:

// pages/index.tsx
import Hello from "@/components/Hello";

export default function Home() {
  return (
    <main>
      <Hello name="Next.js Developer" />
    </main>
  );
}

If this renders correctly in the browser you’re officially free from the jsx-runtime nightmare.

Final Thought

This error was a great reminder that most React and Next.js build issues aren’t caused by missing packages they’re caused by misconfigurations. In my case, a couple of unnecessary overrides completely broke module resolution. Once I cleaned things up and let Next.js handle React the way it was designed to, everything just worked. Sometimes the best fix is not adding more it’s removing what isn’t needed.

Related blog posts