error:0308010C:digital envelope routines::unsupported (Node / OpenSSL 3)
A fresh Node 17+ (or any build using OpenSSL 3) runs an older webpack 4 / CRA / Vue CLI toolchain and dies before the bundle starts. The scary OpenSSL message is a crypto policy clash, not a corrupt install.
The error
Error: error:0308010C:digital envelope routines::unsupported
code: 'ERR_OSSL_EVP_UNSUPPORTED'
It usually appears the moment webpack, react-scripts, vue-cli-service or an old Babel/webpack plugin initialises — at build or dev-server start, not when a user loads the finished static files. Runtime-only apps that never touch those hash APIs keep working.
Why it happens
| Layer | What changed |
|---|---|
| OpenSSL 3 | Default provider no longer allows MD4 and some other legacy algorithms |
| Node 17+ | Links against OpenSSL 3 (Node 16 was still OpenSSL 1.1.1) |
| webpack 4 / old CRA / Vue CLI | Still calls those legacy digests during compilation |
So: same project, Node 16 → fine; Node 18/20/22 → boom. CI images that floated to a newer Node major are a classic surprise trigger.
Temporary workaround
# one shell session
export NODE_OPTIONS=--openssl-legacy-provider
npm run build
# or inline
NODE_OPTIONS=--openssl-legacy-provider npm start
# package.json scripts (team-wide bandaid)
"build": "NODE_OPTIONS=--openssl-legacy-provider react-scripts build"
On Windows cmd.exe use set NODE_OPTIONS=--openssl-legacy-provider before the script; in PowerShell $env:NODE_OPTIONS="--openssl-legacy-provider". The flag re-enables the OpenSSL 3 legacy provider so old hash calls succeed. Treat it as a bridge, not the destination — it papers over an unmaintained toolchain.
Proper fixes
- Upgrade webpack 4 → 5 (and webpack-dev-server / related loaders). Webpack 5 uses supported digests. Budget time for config changes (
optimization,devServer, file-loader → asset modules). - create-react-app:
react-scripts5 helps on some setups but CRA itself is largely unmaintained. Prefer migrating to Vite, Next.js or a maintained webpack 5 template rather than ejecting forever. - Vue CLI: same story — Vue CLI 5 + webpack 5, or move to Vite.
- Pin Node in Docker / CI:
Keep the same major locally, in CI and in the image. Document it with an# bad: floats to whatever is current FROM node:latest # better: explicit major you have tested FROM node:20-bookworm-slimenginesfield in package.json. - Stay on Node 16 only as a last short-term holding pattern — Node 16 is end-of-life and still leaves you on OpenSSL 1.1. Prefer upgrading the bundler.
Build vs runtime
- Build /
npm startfails with 0308010C → toolchain issue above. - Production container serving static files does not need the legacy flag if the assets were built elsewhere on a compatible Node.
- Native addons that call OpenSSL themselves can throw similar ERR_OSSL_* errors at runtime; those need an addon update, not webpack flags.
Related memory / npm errors
Old webpack builds are also heavy: if the process dies with exit 137 instead, see Killed exit code 137 (out of memory). Fresh dependency trees after a Node bump often hit peer conflicts — npm ERESOLVE — or a missing file after a partial install — npm ERR! code ENOENT. Comparing two lockfiles in the text diff tool helps spot what jumped when you changed Node.
Related
Cannot use import statement outside a module · Killed: exit code 137 (OOM) · JavaScript heap out of memory · npm ERESOLVE · npm ERR! code ENOENT · npm EACCES global install · npm ERR! code ELIFECYCLE
Questions
What is error:0308010C:digital envelope routines::unsupported?
OpenSSL 3 (used by Node 17+) refused a legacy crypto algorithm that an older webpack/CRA/Vue CLI toolchain still calls. Upgrade the bundler, or temporarily set NODE_OPTIONS=--openssl-legacy-provider.
Is --openssl-legacy-provider safe?
It re-enables legacy algorithms for that Node process. Fine as a short-term build workaround; do not treat it as the long-term fix — upgrade webpack or move to Vite.
Why did this start after I upgraded Node?
Node 17+ switched from OpenSSL 1.1.1 to OpenSSL 3. The same project on Node 16 often still builds.
Does this affect the browser users of my site?
No. It fails at compile/dev-server time on the machine running Node. Built static assets do not need the legacy flag at serve time.
Should I pin node:16 in Docker forever?
No. Node 16 is end-of-life. Pin a current LTS major and upgrade the bundler so you do not need the legacy provider.
Published .