♓️

【Heroku】 error:0308010C が発生してデプロイに失敗する場合の解決策

2023/11/14に公開

Heroku Pipeline を使って運用しているRailsアプリケーションで、デプロイ時に以下のようなエラーが発生しました。

Error: error:0308010C:digital envelope routines::unsupported

発生したエラー

改めてエラーメッセージ全体を見てみます。

Compilation failed:
  Error: error:0308010C:digital envelope routines::unsupported
      at new Hash (node:internal/crypto/hash:68:19)
      at Object.createHash (node:crypto:138:10)
      at module.exports (/tmp/build_0e3c50c6/node_modules/webpack/lib/util/createHash.js:135:53)
      at NormalModule._initBuildHash (/tmp/build_0e3c50c6/node_modules/webpack/lib/NormalModule.js:417:16)
      at handleParseError (/tmp/build_0e3c50c6/node_modules/webpack/lib/NormalModule.js:471:10)
      at /tmp/build_0e3c50c6/node_modules/webpack/lib/NormalModule.js:503:5
      at /tmp/build_0e3c50c6/node_modules/webpack/lib/NormalModule.js:358:12
      at /tmp/build_0e3c50c6/node_modules/loader-runner/lib/LoaderRunner.js:373:3
      at iterateNormalLoaders (/tmp/build_0e3c50c6/node_modules/loader-runner/lib/LoaderRunner.js:214:10)
      at iterateNormalLoaders (/tmp/build_0e3c50c6/node_modules/loader-runner/lib/LoaderRunner.js:221:10)
      at /tmp/build_0e3c50c6/node_modules/loader-runner/lib/LoaderRunner.js:236:3
      at context.callback (/tmp/build_0e3c50c6/node_modules/loader-runner/lib/LoaderRunner.js:111:13)
      at /tmp/build_0e3c50c6/node_modules/babel-loader/lib/index.js:44:71 {
    opensslErrorStack: [ 'error:03000086:digital envelope routines::initialization error' ],
    library: 'digital envelope routines',
    reason: 'unsupported',
    code: 'ERR_OSSL_EVP_UNSUPPORTED'
  }
  
  Node.js v20.9.0

エラーメッセージにある error:0308010CERR_OSSL_EVP_UNSUPPORTED で検索すると、色々と情報が出てきます。

原因はOpenSSLの互換性

エラーはざっくり以下のような流れで発生していることがわかりました。
1. HerokuがデフォルトでNode.js 20.xをインストールするようになった

If a Node version isn’t specified in the engines section, Node.js 20.x is used automatically.

https://devcenter.heroku.com/articles/nodejs-support

2. Node.js 17.x以降ではOpenSSL 3が使用されるが、Webpackがこれに対応してないため互換性エラーが出る

Node.js の OpenSSL の互換性については、以下の記事で解説されていました。
https://zenn.dev/yogarasu/articles/425732ff408d06

このRailsアプリケーションでは Gem Webpacker で Webpack を使用しているため、OpenSSL の互換性エラーに引っ掛かっていました。

解決策1 - 古いバージョンのOpenSSLを使用する

古い OpenSSL を使用する環境変数を設定することでエラーは解消しました。

Heroku 環境の Node.js でエラーが発生しているため、Heroku に環境変数を設定します。

heroku config:set NODE_OPTIONS='--openssl-legacy-provider' --app APP_NAME

ダッシュボードから環境変数を設定することも可能です。

解決策2 - HerokuのNode.jsをバージョンダウンする(非推奨)

もう1つ、Heroku にインストールされる Node.js を v20.x から v16.x にする方法があります。

こうすることで OpenSSL 3 が使用されなくなり、エラーは解消します。

手順は以下の通りです。

1. Node.js Buildpacksをインストール

インストールされているBuildpacksを確認

heroku buildpacks --app APP_NAME

heroku/nodejs がなかった場合、以下2つのいずれかのコマンドを実行

# 他にBuildpacksが存在しなかった場合
heroku buildpacks:set heroku/nodejs --app APP_NAME

# 別のBuildpacksが既に存在した場合(heroku/ruby 等)
heroku buildpacks:add heroku/nodejs --app APP_NAME

補足:buildpacks:set は単一、buildpacks:add は複数のBuildpacksとして追加します[1]公式ドキュメントより)

2. package.jsonでインストールするNode.jsのバージョンを指定

package.jsonengines セクションを追加します。

package.json
{
  "name": "example-app",
  "description": "a really cool app",
  "version": "1.0.0",
+ "engines": {
+   "node": "16.x"
+ }
}

ただ、この方法はサポート期限切れの v16.x を使用するため、推奨しません。

しかし私の場合は解決策2が必要でした。
というのも実は OpenSSL の互換性エラーとは別のエラーも同時に発生していました。これにより Heroku に環境変数を追加しても、反映されませんでした。

どうやら Heroku はエラーの発生するデプロイは反映せずにロールバックするという仕様みたいです。つまり、片方ずつエラーを解消してもダメということです。
そこで今回は少しややこしいですが、以下の手順でエラーを解決しました。

  • 「Heroku の Node.js を v16.x に指定(解決策2)+ 別のエラー解決」の修正をデプロイ
  • 環境変数に NODE_OPTIONS を追加(解決策1)
  • Herokku の Node.js を v20.x に戻す

まとめ

今回は Heroku で error:0308010C が発生してデプロイに失敗する場合の解決策についてまとめてみました。
私はかなり苦戦したので、同様のエラーで困っている方の助けになると幸いです。

参考サイト

以下のドキュメント、記事を参考にエラーの解決や記事の作成ができました。感謝申し上げます🙇‍♂️

https://devcenter.heroku.com/articles/nodejs-support
https://zenn.dev/yogarasu/articles/425732ff408d06

脚注
  1. Buildpacks を複数インストールする場合には注意が必要です。アプリの第一言語を明確にする必要があります。詳しくはHerokuの公式ドキュメントを参照ください。 ↩︎

Discussion