n8nのCodeノードで「fetch is not defined」が出る原因と直し方

n8n の Code ノードに await fetch(url) と書くと、実行した瞬間に「fetch is not defined」で止まります。弊社でも n8n をアップグレードした直後にこのエラーが本番で出続け、しばらく気づけませんでした。この記事では n8n 本体のソースで原因を確かめ、this.helpers.httpRequest へ書き換える手順をまとめます。
この記事の結論
- n8n 2.19.2 の Code ノードは、JavaScript を「タスクランナー」という別の実行環境に渡して動かします。既定の設定では、そこに用意されている名前の一覧に fetch が入っていないため、呼ぶと ReferenceError になります。
- 直し方は
this.helpers.httpRequest({ method, url, headers, body, json: true })への書き換えです。戻り値は応答の本文そのもので、200 以上 300 未満でない応答は例外として投げられます。 - body はオブジェクトのまま渡します。JSON 文字列にするのは axios の役目なので、自分で JSON.stringify する必要はありません。
- HTML を組み立てる Code ノードでは、fetch( がテンプレート文字列の中か外かを見ます。中ならブラウザで動くので書き換えず、外なら n8n 側で動くので書き換えます。
実際に起きたこと
弊社は 2026-05-06 に n8n を 2.4.6 から 2.19.2 へ上げました。その直後から、Code ノードの中で fetch() を使っていたワークフローが「ReferenceError: fetch is not defined at VmCodeWrapper」で止まるようになりました。
実害が出たのは、検索の計測データを LINE へ日次で届けるワークフローの中の Code ノード2つ、日次レポートと緊急アラートです。エラーは7日連続で続き、2026-05-13 に直しました。止めてあった別のワークフローにも同じ書き方が残っていて、そちらは再び有効にした瞬間に同じエラーで落ちる状態でした。
直す途中で、もうひとつ落とし穴を踏みました。fetch( を機械的に検索すると、HTML を返す Code ノードのテンプレートに書かれたブラウザ側の fetch( まで26箇所引っかかったのです。こちらはブラウザで実行されるので直す必要がないのに、確かめずに「26箇所直す」と数えて後で訂正しました。
原因
Code ノードの JavaScript はタスクランナーで動く
n8n 2.19.2 の Code ノードの実体 Code.node.js は、言語が JavaScript のとき JsTaskRunnerSandbox を作り、startJob(‘javascript’, …) でコードを渡します。受け取って実行する側がタスクランナーです。
公式ドキュメントも、タスクランナーが Code ノードの JavaScript と Python を実行すると説明しています。有効化の設定 N8N_RUNNERS_ENABLED は n8n 2.0 から非推奨で、設定しなくてもこの経路で動きます。
タスクランナーは node:vm の新しいコンテキストでコードを走らせる
タスクランナーの js-task-runner.js は、Node.js 標準の node:vm を読み込み、createContext で新しいコンテキストを作り、その中で runInContext によりコードを実行します。Node.js のドキュメントによると、createContext に渡したオブジェクトがそのコンテキストのグローバルになり、そこにあるのは渡したオブジェクトの持ち物と、標準のグローバルオブジェクトが持つ組み込みの関数です。
それ以外のグローバルは、渡さなければ入りません。buildContext が渡しているのは、require、console、$getWorkflowStaticData、$json などのデータプロキシ、this.helpers 経由の関数、そして getNativeVariables が返す次の名前です。
Buffer
setTimeout, setInterval, setImmediate
clearTimeout, clearInterval, clearImmediate
btoa, atob
TextDecoder, TextDecoderStream
TextEncoder, TextEncoderStream
FormData
この一覧に fetch はありません。Node.js 本体にある fetch が、Code ノードのコードが動くコンテキストには持ち込まれていない。これが原因です。
なお、これは既定の設定の話です。N8N_RUNNERS_INSECURE_MODE を true にすると runDirectly という別の経路になり、new Function と with(context) でランナーのプロセスの中で直接動きます。この記事では既定の経路だけを扱います。
エラー文の形
ユーザーのコードは、VmCodeWrapper という名前の async 関数で包んでから実行されます。
module.exports = async function VmCodeWrapper() {<Code ノードの中身>
}()
スタックトレースに「at VmCodeWrapper」が出るのはこのためです。画面の文言は execution-error.js が組み立てます。「ReferenceError: fetch is not defined」の行を「:」で分け、後ろ側を本文に、前側の「ReferenceError」を説明に入れ、本文の末尾に [line 行番号] を付けます。
公式ドキュメントの立場
Code ノードの公式ドキュメントには「You can’t access the file system or make HTTP requests. Use the following nodes instead:」とあり、HTTP Request ノードを勧めています。一方でソースの runner-types.js には、タスクランナーからメインプロセスへ呼び出せる関数の一覧 EXPOSED_RPC_METHODS があり、helpers.httpRequest が載っています。呼び出しはメインプロセスへ送られ、そこで実際の HTTP 通信が行われます。弊社の本番もこの経路で動いています。
直し方
残っている fetch( を探す
まず、Code ノードに fetch( が残っていないかを調べます。弊社の点検では次の正規表現で検出しています。前にドットや英数字が付かない fetch( だけを拾う形です。
(?<![\w.])fetch\s*\(
ワークフローの中身は API で取り出せます。取り出した JSON を、同じ正規表現で数えます。弊社の点検が Python なので、ここも Python です。
curl -s -H "X-N8N-API-KEY: XXXX" \
http://localhost:5678/api/v1/workflows/<ワークフローID> \
-o wf.json
python3 -c "import re; print(len(re.findall(r'(?<![\w.])fetch\s*\(', open('wf.json').read())))"
注意が要るのが、HTML を返す Code ノードです。jsCode に <!DOCTYPE や <html、document.、location.、alert( といった語があれば、HTML を組み立てているノードの可能性が高いです。ただし、それだけでは拾った fetch( がブラウザ側のものとは決まりません。HTML を返すノードでも、返す前に n8n 側で await fetch() を呼ぶ形はあり得ます。fetch( がテンプレート文字列の中か外かを一つずつ見ます。中ならブラウザで動くので書き換えず、外なら n8n 側で動くので書き換えます。弊社が26箇所を「直す」と数えたのは、ここを見なかったからです。
this.helpers.httpRequest に書き換える
書き換え前です。
const res = await fetch(url, {
method: 'POST',
headers,
body: JSON.stringify(data),
});
return [{ json: { sent: res.ok, status: res.status } }];
書き換え後です。
let sent = false;
let message = '';
try {
await this.helpers.httpRequest({
method: 'POST',
url,
headers,
body: data, // オブジェクトのまま渡す
json: true,
});
sent = true;
} catch (e) {
message = e && e.message ? String(e.message) : String(e);
}
return [{ json: { sent, message } }];
変わった点です。
- URL は第一引数ではなく url という項目で渡し、method、headers、body、json も同じオブジェクトに入れます。項目名は n8n-workflow の型定義 IHttpRequestOptions にあります。
- body はオブジェクトのまま渡します。ソースの convertN8nRequestToAxios を読むと、body はそのまま axios の data に入り、json: true がやることは Accept ヘッダを application/json にすることだけです。data がオブジェクトなら、Content-Type を application/json にして JSON 文字列にするのは axios の役目です。自分で JSON.stringify した文字列を渡すと axios はオブジェクトとして扱わず、Content-Type を自分で付けていなければ application/json も付きません。弊社の点検では、この組み合わせを警告として拾っています。
- 戻り値は応答の本文です。fetch の res.ok や res.status に当たるものは返ってきません。
200 番台以外の応答を扱う
fetch はエラー応答でも例外を投げず、res.ok で判定させます。n8n-core の httpRequest は axios をそのまま呼び、axios の既定の validateStatus は status >= 200 && status < 300 です。それ以外の応答は例外として投げられ、Code ノードの catch に入ります。だから上の書き換えでは try/catch で sent を決めています。
ステータスコードを見たいときは returnFullResponse: true を付けると、戻り値が body、headers、statusCode、statusMessage を持つオブジェクトになります。例外にしたくないときは ignoreHttpStatusErrors: true を付けると、validateStatus が常に true になります。この項目は型定義とソースで確かめただけで、弊社の本番は try/catch の形です。
API で更新したときの反映
弊社の点検では、API で PUT しただけの状態を「DBは新版/実行は旧版」と呼び、PUT の後に deactivate と activate をやり直すことにしています。2.19.2 のソースでは、公開 API の PUT は publishIfActive: true で WorkflowService の update を呼び、nodes か connections が変われば新しい versionId を振り、有効なワークフローなら activateWorkflow でいったん外して登録し直します。つまり PUT だけで新しい版に切り替わる作りです。手順としては勧めず、弊社の運用として記しておきます。
直ったかを確かめる
- 編集画面でその Code ノードだけを実行し、出力の sent が true で返ることを見ます。
- API で取り出した JSON をもう一度数え、n8n 側で実行される fetch( が残っていないことを確かめます。テンプレートの中の分は残っていて構いません。
- スケジュールで動くワークフローなら、次の実行が成功で終わるところまで見届けます。
それでも直らないとき
どの fetch かが分からない
エラー文の末尾の [line 行番号] で場所を絞れます。行番号はスタックトレースのうち、まず VmCodeWrapper を含まない evalmachine の行、無ければ VmCodeWrapper を含む evalmachine の行から取られます。この記事の例のようにトップレベルで await fetch() している場合は後者です。
helpers.httpRequestWithAuthentication を使っている
認証つきの helpers.httpRequestWithAuthentication は、タスクランナーの UNSUPPORTED_HELPER_FUNCTIONS の一覧に入っています。呼ぶと「The function “helpers.httpRequestWithAuthentication” is not supported in the Code Node」という例外になります。弊社は Authorization ヘッダを自分で組み、トークンは環境変数から $env で読んでいます。その $env が「access to env vars denied」で読めないときの直し方は、n8nのCodeノードで「access to env vars denied」が出る原因と直し方 にまとめています。
気づくのが遅れる
このエラーは実行のたびに出ますが、通知がなければ気づけません。弊社は7日間見逃しました。ワークフローの settings.errorWorkflow にエラー通知用のワークフローを設定しておくと、落ちた時点で知らせが届きます。弊社の点検では、有効なワークフローでこれが未設定なら最も重い指摘です。
まとめ
- n8n 2.19.2 の Code ノードは、既定の設定では node:vm の新しいコンテキストでコードを動かし、fetch はそこに渡されていません。
- HTTP 通信は this.helpers.httpRequest で行います。url は項目で渡し、body はオブジェクトのまま、json: true を付けます。
- 戻り値は本文だけで、200 番台以外は例外になります。fetch の res.ok に頼っていた判定は try/catch に書き換えます。
- HTML を返すノードでは、fetch( がテンプレート文字列の中か外かを見ます。中なら書き換えず、外なら書き換えます。
- 直したら次の実行が成功するまで見届け、errorWorkflow で落ちたときの通知を用意します。
参考にした公式ドキュメント
- Code node(n8n Docs)
- Code node Common issues(n8n Docs)
- Set up task runners(n8n Docs)
- VM(Node.js Docs)
n8nの点検と構築のご相談
「Codeノードで fetch is not defined が出る」といったn8nの不具合の点検や、業務の自動化の仕組みづくりをお引き受けしています。






