The build that worked yesterday broke after you only upgraded Node
You didn't touch a single line of code, but the build suddenly exploded. Nine times out of ten, the raw error looks like this. First, confirm one of these three siblings in the logs.
Error: error:0308010C:digital envelope routines::unsupported
at new Hash (node:internal/crypto/hash:71:19)
...
opensslErrorStack: [ 'error:03000086:digital envelope routines::initialization error' ],
library: 'digital envelope routines',
reason: 'unsupported',
code: 'ERR_OSSL_EVP_UNSUPPORTED'The trigger is almost always one thing: you upgraded Node locally with nvm, the CI runner's default Node image moved up (e.g. actions/setup-node default, the node:lts Docker tag), or a teammate changed .nvmrc. In other words, the runtime environment changed, not the code.
Scope: Node.js 17+ (17/18/20/22), webpack 4-based build pipelines — react-scripts (CRA) 4.x, @vue/cli-service 4.x, older gatsby, old storybook, and similar. It happens the same way on every OS that ships OpenSSL 3.0 (Windows/macOS/Linux).
This is not a conceptual lecture — it's a copy-paste runbook. Pin the cause with the 30-second diagnostic table, then apply the 5-minute workaround (Path A) or the root-cause fix (Path B) immediately.
30-second diagnostic table: error string → cause → immediate action
Find the string from your logs in the left column and jump straight to the action on the right.
| Error string | Node version | Likely cause | Immediate action (Path A/B) |
|---|---|---|---|
error:0308010C:digital envelope routines::unsupported | 17+ (default switched at 17) | OpenSSL 3.0 disables legacy hashes (MD4, etc.) by default → webpack 4 chunk hash calculation fails | A: NODE_OPTIONS=--openssl-legacy-provider / B: Upgrade webpack 5 and the build tool |
ERR_OSSL_EVP_UNSUPPORTED | 17+ | Same cause, in Node error-code form | A same / B same |
digital envelope routines::initialization error (03000086) | 17+ | Same cause; nested error that also appears in opensslErrorStack | A same / B same |
The key breakpoint is Node 17. Through Node 16, OpenSSL 1.1.1 was bundled; from Node 17 onward, OpenSSL 3.0 became the default, and 18/20/22 LTS inherited that. OpenSSL 3.0 turns off old legacy-provider algorithms by default for security, so older webpack that used them internally throws the error above.
The cause in one line: OpenSSL 3.0 disables legacy hash algorithms such as MD4 by default → webpack 4's chunk hash (filename hash) calculation fails. You don't need more background than that to fix it.
ESM/CommonJS errors (
Cannot use import statement outside a module,require is not defined) have a completely different cause. If that's you, see the 'Cannot use import statement outside a module' fix runbook — this post covers only the OpenSSL hash family.
Path A — temporary workaround (5-minute cut)
Use this when you need the build to run right now. The --openssl-legacy-provider flag turns OpenSSL's legacy provider back on.
Method 1) Inject the flag directly into package.json scripts
For react-scripts you can pass it as a CLI argument.
{
"scripts": {
"start": "react-scripts --openssl-legacy-provider start",
"build": "react-scripts --openssl-legacy-provider build"
}
}For Vue CLI, put it in front of the service command.
{
"scripts": {
"serve": "vue-cli-service --openssl-legacy-provider serve",
"build": "vue-cli-service --openssl-legacy-provider build"
}
}Method 2) Inject NODE_OPTIONS with cross-env (OS-agnostic, recommended)
If the CLI doesn't accept the flag, or you want one approach that works on every OS, cross-env + NODE_OPTIONS is the safest.
npm i -D cross-env{
"scripts": {
"start": "cross-env NODE_OPTIONS=--openssl-legacy-provider react-scripts start",
"build": "cross-env NODE_OPTIONS=--openssl-legacy-provider react-scripts build"
}
}With cross-env you don't have to care about Windows set vs Unix export. For team projects, this is the recommended approach.
Method 3) Temporary env var in the shell (one-off run)
macOS / Linux (bash·zsh)
export NODE_OPTIONS=--openssl-legacy-provider
npm run buildWindows CMD
set NODE_OPTIONS=--openssl-legacy-provider
npm run buildWindows PowerShell
$env:NODE_OPTIONS = "--openssl-legacy-provider"
npm run buildExpected success: The build that previously died immediately on ERR_OSSL_EVP_UNSUPPORTED proceeds through compilation and you get Compiled successfully or a bundle artifact.
If it doesn't match expectations:
- Still the same error → Check with
node -vthat the Node actually running is 17+. The shell session may have been replaced so the env var never took effect. --openssl-legacy-provider is not allowed in NODE_OPTIONS→ In some Node 22+ situations the flag can be rejected. In that case Path B (upgrade) is effectively mandatory.- If the error string changed to something
ERR_REQUIRE_ESM/import-related, the OpenSSL problem is solved and you have a separate ESM issue.
Method 4) Dockerfile ENV
For container builds, bake it in at the image level (methods 4–5 only on temporary images — see the caveats later).
FROM node:20-alpine
WORKDIR /app
ENV NODE_OPTIONS=--openssl-legacy-provider
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run buildMethod 5) GitHub Actions env block
If it broke in CI, inject the env var into the workflow. Both step level (recommended) and job level work.
name: build
on: [push]
jobs:
build:
runs-on: ubuntu-latest
# job 레벨: 이 job의 모든 step에 적용
env:
NODE_OPTIONS: --openssl-legacy-provider
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
cache: npm
- run: npm ci
# step 레벨: 이 step에만 국한하고 싶을 때
- run: npm run build
env:
NODE_OPTIONS: --openssl-legacy-providerIf you don't pin setup-node's node-version, it will break again when the runner default moves up. Pinning tips — including cache and matrix builds — are in Setting Node build env vars in GitHub Actions.
Path B — root-cause fix: build without the legacy provider
A workaround "revives algorithms that were turned off for security," so it cannot be a permanent fix. Move to the below this sprint.
Step 1 — Check the current webpack version
npm ls webpackExpected result (this is the thing to fix): If you see webpack@4.x.x, that is the root cause of this error.
project@1.0.0
└─┬ react-scripts@4.0.3
└── webpack@4.44.2If webpack@5.x is already showing but you still get the error, webpack 4 may be nested in the dependency tree — check the full tree with npm ls webpack --all.
Step 2 — Build-tool upgrade mapping
webpack 5 usually comes along automatically when you upgrade the build tool. Raising the parent tool is safer than bumping webpack alone.
| Build tool | webpack 5 support starts | Action command |
|---|---|---|
| react-scripts (CRA) | From 5.0.0 | npm i react-scripts@5 |
| @vue/cli-service | From 5.0.0 | npm i -D @vue/cli-service@^5 |
| gatsby | Latest major | npm i gatsby@latest |
| Pure webpack project | 5.x | npm i -D webpack@5 webpack-cli@latest |
# CRA 예시
npm i react-scripts@5
npm dedupeStep 3 — Remove the workaround and verify
After the upgrade, remove every flag and env var you added in Path A and confirm the build passes in a clean state.
# 1) package.json에서 --openssl-legacy-provider / NODE_OPTIONS 제거
# 2) 캐시·모듈 초기화
rm -rf node_modules package-lock.json
npm install
# 3) 환경변수 없는 상태에서 빌드
unset NODE_OPTIONS # Windows PowerShell: Remove-Item Env:\NODE_OPTIONS
npm run buildExpected success: Compiled successfully without NODE_OPTIONS. You no longer depend on the legacy provider.
If it doesn't match expectations:
- Still
ERR_OSSL_EVP_UNSUPPORTED→ Recheck withnpm ls webpack --allwhether webpack 4 is still present. A third-party plugin may be pulling it in. - The error changed to a different build error (e.g. missing polyfills for
Buffer/process) → That's a normal webpack 5 breaking change. Handle it individually withresolve.fallbackornode-polyfill-webpack-plugin. The OpenSSL issue is already solved.
Stick with CRA, or move to Vite?
react-scripts (CRA) is effectively stalled on maintenance, so migrating to Vite has become the default for new projects. If a webpack 4→5 migration is expensive, it's worth weighing a move to Vite with the same effort. Vite is esbuild/Rollup-based, so this OpenSSL issue never happens.
Conclusion + troubleshooting checklist
workaround now, root-cause fix this sprint. Walk through in this order.
- Confirm
0308010C/ERR_OSSL_EVP_UNSUPPORTED/initialization errorin the logs - Confirm 17+ with
node -v(pin the cause) - If you're in a hurry: work around with
cross-env NODE_OPTIONS=--openssl-legacy-provider - Do not permanently freeze the workaround flag into CI — mark it as temporary in the commit message and PR
- Confirm webpack 4 with
npm ls webpack - Upgrade with
react-scripts@5/@vue/cli-service@5/gatsby@latest - Remove the workaround and verify the build passes without
NODE_OPTIONS - Pin the Node version in
.nvmrc,setup-node, and the Docker tag to prevent recurrence
Caution: --openssl-legacy-provider revives algorithms that OpenSSL 3.0 disabled for security. It is only a temporary measure for developer convenience — do not leave it permanently in a production CI pipeline. Use it on the premise that you will strip it out after the root-cause fix (webpack 5).
The key to preventing recurrence is pinning the Node version. Locally use .nvmrc/Volta; in CI, set setup-node's node-version explicitly so a runner default change doesn't shake you — concrete steps are in the Node version management (nvm/Volta) guide.
References: official docs
The primary sources for the behavior, settings, and errors in this post are the official docs below. Check version-specific options and exact behavior there.
FAQ
Q. Can I just leave --openssl-legacy-provider in CI forever?
A. Not recommended. It revives legacy algorithms that were disabled for security, so it is a temporary workaround. The proper path is to upgrade to webpack 5 so the build works without the flag, then remove it.
Q. I upgraded to Node 20/22 LTS and the flag doesn't take effect or is rejected.
A. On recent Node, the legacy-provider flag in NODE_OPTIONS can be restricted. In that case the workaround is unavailable, so Path B (webpack 5 / build-tool upgrade) is effectively mandatory. If the migration cost is high, also consider moving to Vite.
Q. I upgraded webpack to 5 and still get the same error.
A. Check the dependency tree with npm ls webpack --all. If a third-party plugin or nested dependency still pulls in webpack 4, the error continues. Upgrade that package to a current version, or clean up duplicates with npm dedupe.
Nodelog는 모든 콘텐츠의 내용과 출처를 공개 전에 검토합니다. 환경(OS·버전)에 따라 결과가 달라질 수 있는 기술 정보는 공식 문서와 함께 확인하며, 검토 기준과 정정 원칙은 편집 정책에서 안내합니다. 오류를 발견하시면 이메일로 제보해 주세요 — 확인 후 신속히 정정합니다.
Comments
Be the first to comment.