React router app crashing because it can't find package

Hi,

Today our production react router SSR app stopped working after a routine constants change, with this error in the logs:

Aug 7, 07:22:37 PM: ERROR Uncaught Exception {“errorType”:“Runtime.ImportModuleError”,“errorMessage”:“Error: Cannot find module ‘/var/task/node_modules/@mjacksonmjackson/node-fetch-server/dist/node-fetch-server.cjs’”,“stack”:[“Runtime.ImportModuleError: Error: Cannot find module ‘/var/task/node_modules/@mjackson/node-fetch-server/dist/node-fetch-server.cjs’”," at _loadUserApp (file:///var/runtime/index.mjs:1109:17)“,” at async UserFunction.js.module.exports.load (file:///var/runtime/index.mjs:1148:21)“,” at async start (file:///var/runtime/index.mjs:1332:23)“,” at async file:///var/runtime/index.mjs:1339:1"]}

Aug 7, 07:22:37 PM: INIT_REPORT Init Duration: 427.30 ms	Phase: invoke	Status: error	Error Type: Runtime.ImportModuleError

We published an older build from yesterday which works but i’m not really sure what’s happening here, this can also be reproduced with the official react router netlify template, i deployed it here for testing: https://nodefetchservertest.netlify.app/

Any tips would be appreciated!

5 Likes

We have been experiencing the same issue since this morning

Deploying from the CLI works, but deploying through the Netlify dashboard or CI integration breaks the site, even with old commits that previously worked

2 Likes

Same problem here.

@santiago_j_s you said you could deploy it from the CLI it works - did you do anything special? I’ve just tried that and nada, same error.

Nothing, I used `netlify deploy`, this is my netlify.toml in case it helps:

   1   │ [build]
   2   │   command = "react-router build"
   3   │   publish = "build/client"
   4   │
   5   │ [dev]
   6   │   command = "react-router dev"
   7   │   framework = "vite"
1 Like

Thanks mate, but yeah, same issue. I’m calling it a night, hopefully I’ll wake up and it’s magically fixed…

1 Like

I’m experiencing the same issue, as of today.

2 Likes

Same issue as of today

This has happened to us too, I emailed support and haven’t had anything back yet. I also deployed our repo to the point where it was working and it still failed so something must have changed on the Netlify end.

A redeploy this morning doesn’t seem to have fixed anything either.

Will report back here if I get anything back from support.

1 Like

Hi guys, has anyone found any solution for this? we are also facing the same issue since morning

Same problem, not working even with older build

Hi guys, I’ve found a workaround (well, Mr Claude has).

tl;dr the @mjackson/ package has been renamespaced to @remix-run/ but the react-router/node package still has a dependency on the old version. For whatever reason, Netlify (but not Vercel??) is struggling with this.

Here are instructions from Mr Claude. Sorry for the rush but I’ve been at this all morning and I was supposed to be gone half an hour ago!

# Fix for @mjackson/node-fetch-server Deployment Issue

## Problem

When deploying to Netlify, you may encounter this error:

```

Error: Cannot find module ‘@mjackson/node-fetch-server’

```

This happens because `@react-router/node@7.8.0` has a dependency on `@mjackson/node-fetch-server` which has been replaced by `@remix-run/node-fetch-server`. The package was transferred but `@react-router/node` hasn’t been updated yet.

## Solution Overview

We patch `@react-router/node` to use `@remix-run/node-fetch-server` instead of the deprecated `@mjackson/node-fetch-server`.

## Step-by-Step Fix

### 1. Create the postinstall script

Create a file at `scripts/postinstall.js` with the patching logic that will:

- Replace all references to `@mjackson/node-fetch-server` with `@remix-run/node-fetch-server` in the `@react-router/node` package

- Create a backup copy of the package as a fallback

### 2. Add pnpm override

Add this to your `package.json` under the `pnpm` section:

```json

{

“pnpm”: {

*"overrides"*: {

  *"@mjackson/node-fetch-server"*: *"npm:@remix-run/node-fetch-server@^0.8.0"*

}

}

}

```

### 3. Add postinstall script to package.json

Add to your `scripts` section in `package.json`:

```json

{

“scripts”: {

*"postinstall"*: *"node scripts/postinstall.js"*

}

}

```

### 4. Ensure @remix-run/node-fetch-server is installed

Add to your dependencies in `package.json`:

```json

{

“dependencies”: {

*"@remix-run/node-fetch-server"*: *"^0.8.0"*

}

}

```

### 5. Reinstall dependencies

```bash

rm -rf node_modules pnpm-lock.yaml

pnpm install

```

### 6. Verify the fix

Check that the patch was applied:

```bash

grep @remix-run/node-fetch-server” node_modules/@react-router/node/dist/index.js

```

You should see output like:

```

var import_node_fetch_server = require(“@remix-run/node-fetch-server”);

```

### 7. Commit the changes

```bash

git add scripts/postinstall.js package.json pnpm-lock.yaml

git commit -m “Fix @mjackson/node-fetch-server deployment issue”

git push

```

### 8. Deploy

Your deployment should now work without the missing module error.

## How It Works

1. **pnpm override**: Tells pnpm to install `@remix-run/node-fetch-server` whenever any package requests `@mjackson/node-fetch-server`

2. **postinstall script**: After installation, patches the actual `@react-router/node` files to replace the import statements

3. **Backup copy**: Creates a copy of `@remix-run/node-fetch-server` at the `@mjackson` location as a fallback

## Temporary Solution

This is a temporary workaround until `@react-router/node` is updated to use `@remix-run/node-fetch-server` directly. Once that happens, you can remove:

- The `scripts/postinstall.js` file

- The `postinstall` script from package.json

- The pnpm override from package.json

## Troubleshooting

If you still see the error after applying this fix:

1. **Clear your deployment cache**: Most deployment platforms cache node_modules. Clear the cache and redeploy.

2. **Check the postinstall ran**: Look for these lines in your deployment logs:

```

Patching @react-router/node files…

Patched: /path/to/node_modules/@react-router/node/dist/index.js

```

3. **Verify locally**: Run `npm run build` locally and check if it completes without errors.

4. **Check Node version**: Ensure your deployment uses the same Node version as your local environment.

// scripts/patch-build.js

#!/usr/bin/env node
import * as fs from 'node:fs';
import * as path from 'node:path';
import { fileURLToPath } from 'node:url';

const __dirname = path.dirname(fileURLToPath(import.meta.url));
const projectRoot = path.resolve(__dirname, '..');

// Function to recursively find and replace in files
function replaceInFiles(dir, searchStr, replaceStr) {
  const files = fs.readdirSync(dir);
  
  for (const file of files) {
    const filePath = path.join(dir, file);
    const stat = fs.statSync(filePath);
    
    if (stat.isDirectory()) {
      replaceInFiles(filePath, searchStr, replaceStr);
    } else if (file.endsWith('.js') || file.endsWith('.cjs') || file.endsWith('.mjs')) {
      let content = fs.readFileSync(filePath, 'utf8');
      if (content.includes(searchStr)) {
        content = content.replaceAll(searchStr, replaceStr);
        fs.writeFileSync(filePath, content);
        console.log(`Patched: ${filePath}`);
      }
    }
  }
}

// Patch the build output
const buildDir = path.join(projectRoot, 'build');
if (fs.existsSync(buildDir)) {
  console.log('Patching build files to replace @mjackson/node-fetch-server with @remix-run/node-fetch-server...');
  replaceInFiles(buildDir, '@mjackson/node-fetch-server', '@remix-run/node-fetch-server');
}

// Also patch .netlify/functions-internal if it exists
const netlifyDir = path.join(projectRoot, '.netlify/functions-internal');
if (fs.existsSync(netlifyDir)) {
  console.log('Patching Netlify functions to replace @mjackson/node-fetch-server with @remix-run/node-fetch-server...');
  replaceInFiles(netlifyDir, '@mjackson/node-fetch-server', '@remix-run/node-fetch-server');
}
//scripts/postinstall.js

#!/usr/bin/env node
import * as fs from 'node:fs';
import * as path from 'node:path';
import { fileURLToPath } from 'node:url';

const __dirname = path.dirname(fileURLToPath(import.meta.url));
const projectRoot = path.resolve(__dirname, '..');

// Function to patch files
function patchFile(filePath) {
  if (fs.existsSync(filePath)) {
    let content = fs.readFileSync(filePath, 'utf8');
    if (content.includes('@mjackson/node-fetch-server')) {
      content = content.replaceAll('@mjackson/node-fetch-server', '@remix-run/node-fetch-server');
      fs.writeFileSync(filePath, content);
      console.log(`Patched: ${filePath}`);
    }
  }
}

// 1. Patch @react-router/node files directly
const reactRouterNodePath = path.join(projectRoot, 'node_modules', '@react-router', 'node');
if (fs.existsSync(reactRouterNodePath)) {
  console.log('Patching @react-router/node files...');
  patchFile(path.join(reactRouterNodePath, 'dist', 'index.js'));
  patchFile(path.join(reactRouterNodePath, 'dist', 'index.mjs'));
  patchFile(path.join(reactRouterNodePath, 'dist', 'index.d.ts'));
  patchFile(path.join(reactRouterNodePath, 'dist', 'index.d.mts'));
  patchFile(path.join(reactRouterNodePath, 'package.json'));
}

// 2. Also handle pnpm store versions
const pnpmDir = path.join(projectRoot, 'node_modules', '.pnpm');
if (fs.existsSync(pnpmDir)) {
  const dirs = fs.readdirSync(pnpmDir);
  
  for (const dir of dirs) {
    if (dir.startsWith('@react-router+node@')) {
      const pnpmReactRouterPath = path.join(pnpmDir, dir, 'node_modules', '@react-router', 'node');
      if (fs.existsSync(pnpmReactRouterPath)) {
        console.log(`Patching pnpm store: ${dir}`);
        patchFile(path.join(pnpmReactRouterPath, 'dist', 'index.js'));
        patchFile(path.join(pnpmReactRouterPath, 'dist', 'index.mjs'));
        patchFile(path.join(pnpmReactRouterPath, 'dist', 'index.d.ts'));
        patchFile(path.join(pnpmReactRouterPath, 'dist', 'index.d.mts'));
        patchFile(path.join(pnpmReactRouterPath, 'package.json'));
      }
      
      // Also copy @remix-run/node-fetch-server to @mjackson location as backup
      const reactRouterNodePath = path.join(pnpmDir, dir, 'node_modules');
      const mjacksonPath = path.join(reactRouterNodePath, '@mjackson');
      const remixRunPath = path.join(reactRouterNodePath, '@remix-run', 'node-fetch-server');
      
      if (!fs.existsSync(mjacksonPath)) {
        fs.mkdirSync(mjacksonPath, { recursive: true });
      }
      
      const linkPath = path.join(mjacksonPath, 'node-fetch-server');
      try {
        fs.rmSync(linkPath, { recursive: true, force: true });
      } catch {}
      
      if (fs.existsSync(remixRunPath)) {
        try {
          fs.cpSync(remixRunPath, linkPath, { recursive: true });
          console.log(`Backup copy: ${remixRunPath} -> ${linkPath}`);
        } catch (err) {
          console.error(`Failed to copy: ${err.message}`);
        }
      }
    }
  }
}
// package.json scripts
"build": "react-router build && node scripts/patch-build.js && node netlify/prepare.js",
"postinstall": "node scripts/postinstall.js"

Great stuff, thanks! I’ll give this a try and report back! :slightly_smiling_face:

I just had to add:

"pnpm": {
  "overrides": {
    "@mjackson/node-fetch-server": "npm:@remix-run/node-fetch-server"
  },
},

To my package.json and it started working again, so you might want to try that (assuming you’re using pnpm) without the script too to see if that works for you too!

3 Likes

Weird, that’s the first thing I tried, perhaps I hadn’t cleared the cache or something. I’ll try this when I’m back later this afternoon and if it solves it for me I’ll delete the other reply so people see your solution first.

1 Like

Hi folks, thank you for reporting this and for sharing all this info. We’re looking into this now!

2 Likes

We’ve narrowed this down to a regression in our Netlify Functions bundling system.

In the meantime, a simple workaround is to npm i -g netlify-cli@23.0.0 (this is the version of Netlify CLI before this was introduced) and use netlify deploy.

The bug is also present on the Netlify build system (used on git commits, webhooks, etc.). We’ll get that rolled back ASAP. I’ll update here when that’s done.

4 Likes

We’ve now found the root cause, which was an update to an open-source dependency we use for dependency tracing which introduced new, faulty behaviour when using node 22.

We’ll have a fix rolled out to the build system within an hour or so as well as a new release of Netlify CLI with a fix.

In the meantime, it appears yet another workaround is to build with node 20.

3 Likes

Final update: this bug is now fixed in the Netlify build system as well as in netlify-cli@23.1.3.

Thanks again for all the great reports and for your patience.

5 Likes

Amazing, thank you! Will remove the workaround and see how we go. Thanks again for the speedy fix :slight_smile:

1 Like