Fix Module not found: Can't resolve 'encoding' in Vercel
Next.js

Fix Module not found: Can't resolve 'encoding' in Vercel

You see "Module not found: Can't resolve 'encoding'" in your Vercel deployment logs. This guide explains why it happens with cross-fetch/node-fetch and how to fix it permanently.

2026-06-14
8 min read
Fix Module not found: Can't resolve 'encoding' in Vercel

TL;DR#

If you're seeing Module not found: Can't resolve 'encoding' in '/vercel/path0/node_modules/cross-fetch/node_modules/node-fetch/lib', the cause is usually a missing encoding dependency required by node-fetch inside cross-fetch, which Next.js doesn’t polyfill by default. Fix it by installing encoding and configuring Webpack to include Node.js polyfills.

If that doesn't work, scroll to verify the fix — there are two common variants this guide also covers.

What you'll see#

plaintext
Module not found: Can't resolve 'encoding' in '/vercel/path0/node_modules/cross-fetch/node_modules/node-fetch/lib'

It happens when you deploy a Next.js app to Vercel that uses the Supabase JS client, which transitively depends on cross-fetch. The error appears during the Next.js build process — either locally with next build or in Vercel’s CI logs — and prevents the app from deploying.

The behavior is the same across Next.js 13+, Vercel deployments, and projects using @supabase/supabase-js. It does not occur in pure Node.js environments where encoding is more likely to be present.

Root cause#

The root cause is a mismatch between Node.js runtime expectations and Next.js’s browser-first build strategy. cross-fetch (a popular polyfill for window.fetch) depends on node-fetch, which in turn uses the encoding package to handle non-UTF-8 text encodings — a Node.js-specific feature. When Next.js bundles your code for the browser, it strips out Node.js built-ins like buffer, process, and encoding unless explicitly configured.

This becomes a problem because node-fetch@2.x (still used by older cross-fetch versions) imports encoding unconditionally in its source code. The import path looks something like:

js
// node-fetch/lib/fetch.js (v2.6.7)
const { TextDecoder, TextEncoder } = require('encoding');

But encoding is not installed — and Next.js’s Webpack config does not include encoding in its polyfill set by default. Vercel’s build environment enforces this strictness, so the build fails with a module resolution error.

The relevant dependency chain is: cross-fetchnode-fetch@2.xencoding. When Webpack attempts to resolve the require('encoding') call inside node-fetch@2.x, it cannot find the package in the dependency tree (unless explicitly added to package.json), and the build fails with the module resolution error shown above.

This is not a bug in Supabase or cross-fetch — it’s a known limitation of using Node.js polyfills in a browser-oriented framework like Next.js.

The fix#

The fix has three parts: install encoding, configure Webpack to polyfill Node.js built-ins, and ensure cross-fetch uses a version that doesn’t pull in node-fetch@2.

json
{
  "dependencies": {
    "encoding": "^0.1.13",
    "cross-fetch": "^4.1.0"
  }
}

That single change addresses the cause because encoding satisfies the runtime dependency, and cross-fetch@4.1.0+ uses node-fetch@3, which no longer requires encoding — it relies on the global TextEncoder/TextDecoder APIs available in modern browsers and Node.js 17+.

Step by step#

  1. Open package.json.
  2. Add "encoding": "^0.1.13" to dependencies.
  3. Update "cross-fetch" to "^4.1.0" (or higher, as of 2026, v4.1.0 is the latest stable).
  4. Run npm install or yarn install.
  5. Restart your dev server with next dev or run next build.

If you’re using Yarn, ensure you run yarn install — not just yarn add — to avoid version conflicts in the lockfile.

Verify the fix#

Run:

bash
npm run build

You should see:

text
✓ Ready in X.Xs
✓ Creating an optimized production build
✓ Compiled successfully

Instead of the Module not found: Can't resolve 'encoding' error.

If you're still seeing the error, two common variants exist:

Variant A — encoding installed but Webpack still fails#

Sometimes encoding is present, but Next.js’s Webpack configuration still excludes it due to strict externals or resolve.fallback settings. This happens if you’ve customized next.config.js.

To diagnose, check next.config.js for:

js
// next.config.js
module.exports = {
  webpack: (config, { isServer }) => {
    if (!isServer) {
      config.resolve.fallback = {
        ...config.resolve.fallback,
        fs: false,
        net: false,
        tls: false,
      };
    }
    return config;
  },
};

If encoding is missing from fallback, add it:

js
// next.config.js
module.exports = {
  webpack: (config, { isServer }) => {
    config.resolve.fallback = {
      ...config.resolve.fallback,
      encoding: false, // ← explicitly disable polyfill for encoding
    };
    return config;
  },
};

Why false? Because encoding is only needed at runtime in Node.js environments (like server-side rendering), not in the browser. Setting it to false tells Webpack to ignore it in client bundles, avoiding the error while keeping SSR safe.

Variant B — Supabase client uses cross-fetch indirectly via @supabase/realtime#

If you’re using Supabase’s Realtime client (@supabase/realtime-js), it may pull in cross-fetch as a transitive dependency, bypassing your top-level package.json resolution. This causes version mismatches.

To fix, add a resolutions field in package.json:

json
{
  "resolutions": {
    "cross-fetch": "^4.1.0"
  }
}

Then run npx npm-check-resolutions to enforce the override and reinstall dependencies.

Why this happens (and how to avoid it next time)#

This error occurs because Next.js optimizes for the browser by default, stripping Node.js polyfills unless explicitly requested. The encoding package is one of many Node.js-specific modules that don’t exist in browsers — others include buffer, process, and stream. For projects that need broader Node.js core API coverage in the browser, the node-polyfills Webpack plugin automatically maps Node built-ins (like crypto, path, and stream) to browser-compatible shims, though for this specific case a targeted resolve.fallback entry is enough.

To prevent this in the future, adopt two practices:

  1. Pin fetch polyfills to modern versions. Avoid cross-fetch@2.x — it depends on node-fetch@2, which requires encoding. Use cross-fetch@4.1.0+, which uses node-fetch@3 and relies on native TextEncoder/TextDecoder.

  2. Configure Webpack polyfills explicitly. In next.config.js, always include encoding: false in resolve.fallback for client bundles. This tells Webpack to skip polyfilling it in the browser, avoiding the resolution error.

Here’s a production-ready next.config.js snippet:

js
// next.config.js
const nextConfig = {
  webpack: (config, { isServer }) => {
    if (!isServer) {
      config.resolve.fallback = {
        ...config.resolve.fallback,
        fs: false,
        net: false,
        tls: false,
        encoding: false,
      };
    }
    return config;
  },
};
 
module.exports = nextConfig;

I cover this pattern — along with Supabase-specific optimizations like connection pooling and environment variable handling — in Deploying Next.js + Supabase to Production.

FAQ#

Q: Can I just install encoding without changing Webpack?
A: Sometimes — if your app only runs in Node.js (e.g., server-side rendering), installing encoding may suffice. But for full-stack Next.js apps, you must configure Webpack to avoid client-side bundle errors.

Q: Why does this only happen on Vercel and not locally?
A: Vercel’s build environment enforces stricter module resolution than local dev servers. Locally, next dev may cache or skip some checks, but next build (and Vercel’s CI) will catch the missing dependency.

Q: Is encoding safe to include in production?
A: Yes — it’s a small, well-maintained package (20+ years old) used by many Node.js libraries. But in browser bundles, it’s better to disable it via Webpack (encoding: false) since modern browsers have native TextEncoder.

Frequently Asked Questions

|

Have more questions? Contact us

Written by

Mahdi Br
Mahdi Br

Full-Stack Dev — Next.js & Supabase

Solo developer building SaaS products with Next.js and Supabase. Writing about production patterns the official docs skip.

Remote

One email a month — no fluff

RLS gotchas, Next.js cache debugging, and the one Supabase setting that bit me last month.