😽

TypeError: Response body object should not be disturbed or locked

2024/05/11に公開

RemixとClerkを使っていたときに遭遇したエラーです。

action
export const action: ActionFunction = async (args: ActionFunctionArgs) => {
    const formData = await args.request.formData();
    const actionType = formData.get('_action');    
    console.log(formData);

    const res = await getAuth(args);
    console.log(res);

    
    return null;
};

これだとエラーが発生して落ちます。

解決策:

await getAuth(args);をaction関数の最初にもってくる。

action
export const action: ActionFunction = async (args: ActionFunctionArgs) => {
    const res = await getAuth(args);
    const formData = await args.request.formData();
    const actionType = formData.get('_action');    
    console.log(formData);


    console.log(res);

    
    return null;
};

よくわからないけど、なぜかこれだと動くのでとりあえずヨシ

補足:supabaseのClientを呼び出す場合も

action
export const action: ActionFunction = async (args: ActionFunctionArgs) => {
    const supabase = await getSupabaseClient(args);

なぜこの現象が起きたのでしょうか?

GPTの回答:

このエラーは、JavaScriptでfetch APIやその他のネットワークリクエストを使用している際に、リクエストのレスポンスボディがすでに読み取られているか、使用中のためにロックされている場合に発生します。エラーメッセージ「Response body object should not be disturbed or locked」は、レスポンスオブジェクトが「disturbed」(すでに操作されている)か「locked」(ロックされている)ということを指します。

あなたが示した最初のコードと修正後のコードを見ると、主要な変更点はgetAuth関数の呼び出し位置です。最初のコードでは、formData() 関数を呼び出してフォームデータを取得した後に getAuth 関数を呼び出しています。この時点でリクエストボディがすでに読み取られている可能性があります。

修正後のコードでは、getAuth 関数を最初に呼び出し、その後に formData() を呼び出しています。これにより、getAuth 関数がリクエストボディを読み取ったり、なんらかの形でそれに影響を与えたりすることなく、安全にフォームデータを処理することが可能になります。この順序の変更が、エラーが解消される理由です。

つまり、getAuth関数内でリクエストボディにアクセスまたは変更が行われていた場合、その後にformData()を呼び出すと、既に使用されているためエラーが発生する可能性があります。修正後のコードでは、この問題を回避しています。

Discussion