新しいドキュメントやサンプルで見かけた crypto.hash() をそのまま使ったら、手元やサーバーの Node で次のエラーが出て落ちることがあります。
TypeError: crypto.hash is not a function
at Object.<anonymous> (/app/index.js:3:20)
コピペ検索用の表記ゆれです。いずれも同じ原因です。
TypeError: crypto.hash is not a functioncrypto.hash is not a function
これまで紹介してきた「古い Node に新しい API が無い」ケースと向きが逆で、crypto.hash が追加されたのが Node 20.12.0(と 21.7.0)と新しく、それより前の版には無いのが原因です。crypto モジュール自体はどの版にもありますが、hash メソッドだけが新しい版にしか無いため、is not defined ではなく is not a function という形で出ます。
厄介なのは版の並びです。crypto.hash は 現行 LTS だった 20 系に 20.12.0 で入り、当時の最新だった 21 系には 21.7.0 で入りました。そのため「バージョン番号が大きいほうには必ずある」とは限りません。21.6 は 20.12 より番号が大きいのに crypto.hash は無い、という逆転が起きます。「新しめの Node なら大丈夫だろう」で 21.6 を使っていると、20.12 では動くコードがこちらでだけ落ちます。
どの版に crypto.hash があるのか
crypto.hash(ハッシュ値を一発で計算する関数)は複数のリリース系列に分けて追加されました。系列ごとに入った版が違います。
| Node の版 | crypto.hash | 挙動 |
|---|---|---|
| 20.11 以前 | 無し | TypeError: crypto.hash is not a function |
| 20.12.0 以降(20 系) | 有り | そのまま使える |
| 21.0〜21.6 | 無し | TypeError: crypto.hash is not a function |
| 21.7.0 以降(21 系) | 有り | そのまま使える |
| 22 以降 | 有り | そのまま使える |
同じ機能でも、LTS 系列(20)と現行系列(21)で入ったマイナー版がずれています。だから 20.12 と 21.6 のように「古いほうにはあって、新しいほうには無い」区間ができます。単純に版番号の大小では判断できないのがこのエラーの引っかかりどころです。
crypto.hash は何をするものか
crypto.hash(algorithm, data, outputEncoding) は、ハッシュ値を1行で計算するための関数です。従来は crypto.createHash(...).update(...).digest('hex') と3段階で書いていた処理を、1回の呼び出しにまとめたものです。短く書けるぶん新しいサンプルで見かけますが、その分だけ対応する版が新しく、古い版に持ち込むと落ちます。加えて crypto.hash は追加後しばらく実験的(Stability 1・experimental)扱いで、Node 22 系でもその位置づけのままでした。長く保守するコードでは、次の解決1(createHash に戻す)のほうが版・安定度の両面で無難です。
再現(最小構成)
次の1ファイルを置きます。
// index.js
const crypto = require('node:crypto');
console.log(crypto.hash('sha256', 'errfix', 'hex'));
これを Node 20.11 以前や 21.0〜21.6 で node index.js すると TypeError: crypto.hash is not a function が出て、終了コードは 1 になります。Node 20.12 以降(または 21.7/22 以降)なら SHA-256 のダイジェスト(16 進文字列)が表示されます。
解決
1. crypto.createHash に書き換える(どの版でも動かしたいとき)
crypto.hash は createHash().update().digest() の短縮版なので、元の書き方に戻せばどの版でも動きます。古い Node をサポート対象に含むなら、こちらが確実です。
// index.js(createHash に戻した)
const crypto = require('node:crypto');
const digest = crypto.createHash('sha256').update('errfix').digest('hex');
console.log(digest);
新旧どちらの版でも通したいコードなら、crypto.hash があるときだけ使う分岐にできます。
const crypto = require('node:crypto');
function sha256Hex(input) {
if (typeof crypto.hash === 'function') {
return crypto.hash('sha256', input, 'hex');
}
return crypto.createHash('sha256').update(input).digest('hex');
}
2. Node を上げる(crypto.hash を使い続けたいとき)
短い crypto.hash の書き方を使い続けるなら、実行する Node を対応版へ上げます。20 系なら 20.12.0 以降、22 以降ならどの版でも使えます。今から揃えるなら、サポート中の LTS(22 以降)にするのが安全です。20 系に留まる事情があるなら 20.12.0 以降ですが、20 も 21 もすでに EOL(サポート終了)である点は踏まえてください。ここで気をつけるのは、CI・本番の Docker ベースイメージが crypto.hash の入った版かどうかで、番号の大小ではなく「20.12 以降 / 21.7 以降 / 22 以降」で確認することです。
切り分け(似ているが原因が違うもの)
- 番号が大きい Node なのに落ちる:
crypto.hashは 20.12 で LTS に入り、21 系は 21.7 まで入りませんでした。21.6 のように「20.12 より新しいのに無い」版があるのはこのためです。使っている版が 20.12 以降 / 21.7 以降 / 22 以降のいずれかに当てはまるかで判断してください。 - 逆向き(古い Node に新しい標準 API が無い):
crypto.hashは「新しい API を古い版に持ち込んで落ちる」例ですが、fetch・structuredClone・AbortControllerのように「古い Node にそもそも無い」グローバル API も、同じくis not definedやis not a functionで落ちます。原因は共通で、対処は Node を上げるか従来の書き方・ポリフィルに寄せるかです。fetchは ReferenceError: fetch is not defined の直し方、crypto.randomUUIDは TypeError: crypto.randomUUID is not a function の直し方 を参照してください。 cryptoがundefinedで落ちた:Cannot read properties of undefined (reading 'hash')のようにcrypto自体が無いなら、これは版の問題ではなくrequire('node:crypto')(ESM ならimport)の書き忘れです。