MeWrite Docs

Failed to fetch (Node.js)

Node.js環境でfetch APIを使用した際に発生するFailed to fetchエラーの原因と解決策

概要

Node.js 18以降のネイティブfetch、またはnode-fetchライブラリを使用した際に発生するFailed to fetchエラーについて、Node.js環境固有の原因と解決策を解説します。

ブラウザ環境との違いや、サーバーサイド特有の問題に焦点を当てています。

汎用的な原因と解決策はFailed to fetchを参照してください。

エラーメッセージ

TypeError: Failed to fetch
TypeError: fetch failed
cause: Error: connect ECONNREFUSED 127.0.0.1:3000
TypeError: fetch failed
cause: Error: getaddrinfo ENOTFOUND api.example.com

Node.js固有の原因

原因1: DNS解決の問題(IPv4/IPv6)

Node.jsはデフォルトでIPv6を優先することがあり、IPv4のみ対応しているサーバーへの接続が失敗します。

確認方法:

1
2
# DNSの解決結果を確認
node -e "require('dns').lookup('localhost', { all: true }, (err, addresses) => console.log(addresses))"

解決策:

1
2
3
4
5
6
7
import dns from 'dns';

// IPv4を優先する設定
dns.setDefaultResultOrder('ipv4first');

// その後fetchを実行
const response = await fetch('http://localhost:3000/api/data');

または、明示的にIPアドレスを指定:

1
2
// localhostの代わりに127.0.0.1を使用
const response = await fetch('http://127.0.0.1:3000/api/data');

原因2: 自己署名証明書・プライベートCA

開発環境やイントラネットで自己署名証明書を使用している場合、SSL検証に失敗します。

確認方法:

1
2
# 証明書の検証
openssl s_client -connect internal-api.example.com:443

解決策(node-fetch使用時):

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
import https from 'https';
import fs from 'fs';

// カスタムCAを指定
const agent = new https.Agent({
  ca: fs.readFileSync('/path/to/custom-ca.pem')
});

const response = await fetch('https://internal-api.example.com', {
  agent
});

解決策(Node.js 18+ ネイティブfetch):

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
import https from 'https';
import fs from 'fs';

// undiciのdispatcherを使用
import { Agent } from 'undici';

const dispatcher = new Agent({
  connect: {
    ca: fs.readFileSync('/path/to/custom-ca.pem')
  }
});

const response = await fetch('https://internal-api.example.com', {
  dispatcher
});

開発環境のみ(非推奨):

1
2
// 本番環境では絶対に使わないこと
process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0';

原因3: プロキシ設定

企業ネットワークなどでプロキシが必要な環境で、プロキシ設定が行われていない場合。

確認方法:

1
2
3
# 環境変数を確認
echo $HTTP_PROXY
echo $HTTPS_PROXY

解決策:

1
2
3
4
5
6
7
import { ProxyAgent } from 'undici';

const proxyAgent = new ProxyAgent('http://proxy.example.com:8080');

const response = await fetch('https://api.example.com', {
  dispatcher: proxyAgent
});

または環境変数を設定:

1
2
export HTTP_PROXY=http://proxy.example.com:8080
export HTTPS_PROXY=http://proxy.example.com:8080

原因4: タイムアウト設定

デフォルトのタイムアウトが短い、または設定されていない場合。

解決策:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
// AbortControllerでタイムアウトを設定
const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), 30000); // 30秒

try {
  const response = await fetch('https://api.example.com/slow-endpoint', {
    signal: controller.signal
  });
  clearTimeout(timeoutId);
  return await response.json();
} catch (error) {
  if (error.name === 'AbortError') {
    throw new Error('Request timed out');
  }
  throw error;
}

原因5: Keep-Alive接続の問題

サーバー側でKeep-Alive接続が切断された後に再利用しようとした場合。

解決策:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
import { Agent } from 'undici';

const agent = new Agent({
  keepAliveTimeout: 10000,  // 10秒
  keepAliveMaxTimeout: 30000  // 最大30秒
});

const response = await fetch('https://api.example.com', {
  dispatcher: agent
});

デバッグ方法

詳細なエラー情報を取得

1
2
3
4
5
6
7
try {
  const response = await fetch('https://api.example.com');
} catch (error) {
  console.error('Error:', error.message);
  console.error('Cause:', error.cause);  // Node.js固有の詳細情報
  console.error('Code:', error.cause?.code);  // ECONNREFUSED, ENOTFOUND等
}

NODE_DEBUGで詳細ログ

1
NODE_DEBUG=fetch,undici node your-script.js

よくある間違い

  • process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0'を本番環境で使用する
  • IPv6環境を考慮せずにlocalhostを使用する
  • プロキシ環境でプロキシ設定を忘れる
  • node-fetchとネイティブfetchのAPI差異を見落とす

まだ解決しない場合

診断ハブに戻る

関連エラー

関連エラー

Node.js の他のエラー

最終更新: 2026-02-04