ERR_OSSL_EVP_UNSUPPORTED

Node 17+ Webpack ERR_OSSL_EVP_UNSUPPORTED Fix That Actually Works

Node 17 switched to OpenSSL 3, breaking Webpack 4's MD4 hashing. Here's how to fix it in 30 seconds, 5 minutes, or the proper long-term way.

You updated Node.js to 17 or 18, ran npm start, and now Webpack is spewing a wall of red with error:0308010C:digital envelope routines::unsupported at the bottom. Nothing you changed in your code caused this. Node did it to you on update.

Here's what happened: Node 17 ships with OpenSSL 3.0. OpenSSL 3 moved MD4 (a hashing algorithm Webpack 4 uses by default) into the "legacy" provider, which is off unless you ask for it. So the moment Webpack tries to hash a module, OpenSSL throws ERR_OSSL_EVP_UNSUPPORTED and dies. Common trigger: you're on a Create React App 4, Angular 11–12, or Vue CLI 4 project — all of those are pinned to Webpack 4.

There are three ways out. Start at step one. Stop when your build runs.

Fix 1: The 30-second fix (set the legacy provider flag)

This tells Node to re-enable the OpenSSL legacy mode that Webpack 4 expects. It's a one-line environment variable. Not elegant, but it gets you back to work.

On macOS and Linux

export NODE_OPTIONS=--openssl-legacy-provider
npm start

On Windows CMD

set NODE_OPTIONS=--openssl-legacy-provider
npm start

On Windows PowerShell

$env:NODE_OPTIONS="--openssl-legacy-provider"
npm start

After you run this, the build should start compiling normally — no more ERR_OSSL_EVP_UNSUPPORTED. The catch: that env var only lasts for the current terminal session. Close the window and it's gone.

To make it stick, add it to your package.json scripts. On Windows you'll need cross-env so the syntax works everywhere:

npm install --save-dev cross-env

Then edit your scripts:

"scripts": {
  "start": "cross-env NODE_OPTIONS=--openssl-legacy-provider react-scripts start",
  "build": "cross-env NODE_OPTIONS=--openssl-legacy-provider react-scripts build"
}

One thing to watch: if you're on Node 20+, this flag sometimes gets rejected on certain platforms (there were regressions in early Node 20 builds). If you see node: --openssl-legacy-provider is not allowed in NODE_OPTIONS, skip to Fix 2 or 3.

Fix 2: The 5-minute fix (change Webpack's hash function)

If you don't want to enable legacy crypto (and you shouldn't, long-term — MD4 is broken), tell Webpack to use a modern hash instead. This is a one-line config tweak and it's the fix I'd actually recommend for most projects.

Open your webpack.config.js (or vue.config.js / angular.json for framework projects) and find your output block. Add hashFunction: 'xxhash64':

module.exports = {
  // ... your existing config ...
  output: {
    hashFunction: 'xxhash64',
    // ... other output options
  }
};

For Angular projects, edit angular.json and add "hashFunction": "xxhash64" under the options object of your build target.

For Vue CLI / vue.config.js:

module.exports = {
  configureWebpack: {
    output: {
      hashFunction: 'xxhash64'
    }
  }
}

Then run npm start again. Expected result: Webpack compiles cleanly with no error, and your bundle filenames now use xxhash64 instead of MD4 (you'll see filenames like main.a1b2c3d4.js — same format, different hash underneath).

Heads up: this only works if you can edit the Webpack config directly. Create React App hides its config behind react-scripts, so you can't just add this line. CRA users — see Fix 3, or eject, or move to Vite. Honestly, move to Vite.

Fix 3: The 15-minute fix (upgrade off Webpack 4)

The real fix is to stop using Webpack 4. It's end-of-life, it uses a broken hash algorithm by default, and every workaround above is a bandage on a wound that shouldn't exist.

Option A: Upgrade to Webpack 5

Webpack 5 uses xxhash64 by default. No flags, no config hacks, no error. If your project is on raw Webpack, upgrade:

npm install --save-dev webpack@latest webpack-cli@latest

You'll need to fix a few things. node.fs: 'empty' no longer works the same way. optimization.splitChunks defaults changed. And polyfills for Node core modules (crypto, buffer, path) are gone — you have to add them yourself now. Budget 15–30 minutes for a small project, longer for one with lots of loaders.

Option B: Migrate Create React App to Vite

If you're on CRA and getting this error, the fastest path forward is Vite. It's a fundamentally different bundler (esbuild for dev, Rollup for prod), it starts in under a second on most projects, and it doesn't have this class of OpenSSL problem.

npm create vite@latest my-app -- --template react
cd my-app
npm install
npm run dev

Copy your src/ folder over, update imports that relied on CRA-specific features (process.env.REACT_APP_* becomes import.meta.env.VITE_*), and you're done. You should see Vite's dev server boot in the terminal within a second or two — no compiling message like Webpack shows, it just serves.

Option C: Angular — upgrade Angular CLI

Angular 13+ ships with Webpack 5. Upgrade with the official tool:

npx ng update @angular/cli @angular/core

Expect the updater to walk you through breaking changes. Angular 12 → 13 → 14 → 15 → 16 is the clean path; jumping multiple majors at once usually creates more work than it saves.

Which fix should you pick?

Here's the short version:

Your situationDo this
Need it working right now, will clean up laterFix 1 (NODE_OPTIONS flag)
Own the Webpack config, want a real fix todayFix 2 (hashFunction: xxhash64)
On Create React App, greenfield-ish projectFix 3, Option B (Vite)
Angular 11 or 12Fix 3, Option C (ng update)
Raw Webpack 4, small projectFix 3, Option A (Webpack 5)

Why you shouldn't leave Fix 1 in place forever

I've seen teams ship --openssl-legacy-provider to production CI and forget about it for two years. Don't do that. That flag re-enables a whole family of deprecated OpenSSL algorithms (MD4, MD5 for signatures, RC4, and others) process-wide. It's fine for a local dev fix to unblock yourself, but on a build server it's a security smell that auditors will flag.

If you deploy with the legacy flag on, you're telling anyone who reads your CI config that nobody's paying attention to which crypto primitives your toolchain uses. That's the kind of thing that turns into a CVE headline six months later.

Fix 2 or Fix 3. Those are the ones you can leave in place.

Still seeing the error after Fix 1?

Two things to check:

  • Did the env var actually get picked up? Run node -e "console.log(process.env.NODE_OPTIONS)". If it prints undefined, your shell didn't export it — recheck the syntax for your OS.
  • Are you running through a wrapper that spawns a fresh Node process with a clean env? Some Docker images and CI runners strip NODE_OPTIONS. In that case set it inside the container's entrypoint or in the CI config, not in your local shell.

If you're still stuck after that, paste the full error into a search — the OpenSSL code error:0308010C is the identifier you want to search on, not just ERR_OSSL_EVP_UNSUPPORTED. They show up in different parts of the same error output and lead to different Stack Overflow threads.

Related Errors in Programming & Dev Tools
Shared module not found for version Webpack 5 Module Federation: Fixing 'Shared module not found for version' externally-managed-environment Fix 'externally-managed-environment' pip error on Linux TS2339 TS2339 in Mapped Types: Why Conditional Returns Break Property Access MissingPluginException Flutter MissingPluginException on iOS after dependency upgrade

Was this solution helpful?

EP
Erropedia Team
Tech Support Editors
The Erropedia editorial team researches and documents real-world tech errors from across Windows, Linux, macOS, networking, databases, cloud platforms, and more. Every solution is reviewed for accuracy and updated as software and systems evolve.