[小ネタ]node-fetch で TypeError: body used already for エラーが発生した場合の対応

2023.01.30

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

こんにちは、クラスメソッド CX 事業本部 Delivery 部のジョン・ヒョンジェです。

今回は node-fetch を使う時に、TypeError: body used already for というエラーが出た場合の原因と解決方法について話したいと思います。

エラーの原因

import fetch from 'node-fetch';

const response = await fetch("https://example.com", {
  //param 省略
})

const responseText = response.text()
if(!response.ok) {
  throw new Error(responseText)
}

const responseJson = response.json()
.
.
//省略(responseJsonを使った処理)
.
.

説明のために、例のコードを書いてみました。このコードを実行すると TypeError: body used already for エラーが発生します。

エラーの原因はエラー内容から分かるように、const responseText = response.text() で response オブジェクトを一回使ったのに、const responseJson = response.json() でもう一回使おうとしたからです。node-fetch 内部のコードを見ると、response オブジェクトが一回使われたら、bodyUsed を true にし、2回からはエラーを出すようにしていることがわかります。

エラーの解消

エラーの解消方法としては "response オブジェクトが同時に2回以上使われないようにする"になります。上の例のコードだと Error を throw するときのメッセージを他のものにするか、

import fetch from 'node-fetch';

const response = await fetch("https://example.com", {
  //param 省略
})

if(!response.ok) {
  const responseText = response.text()
  throw new Error(responseText)
}

const responseJson = response.json()
.
.
//省略(responseJsonを使った処理)
.
.

のように、const responseText = response.text() を条件分岐の内に配置して、response オブジェクトが同時に2回使われないようにすることで解決ができます。

参考)