Hi, I encounter a strange bug when doing client upload on preview env (it works as expected locally with ngrok and I did not try it in production as huh... test in production is never a good idea).
The problem is related to the random hidden use of window object inside the upload api route. Random because I use the upload function client side to upload a lot of files, sometimes the api route handle the request normally and all works as expected, sometimes not without any difference in upload() parameters client side. Here is a simple implementation :
import { getServerSession } from "next-auth";import { NextRequest, NextResponse } from "next/server";import { authOptions } from "../../auth/[...nextauth]/route";import { handleUpload, type HandleUploadBody } from "@vercel/blob/client";
export async function POST(request: NextRequest) { const body = (await request.json()) as HandleUploadBody;
try { const jsonResponse = await handleUpload({ body, request, onBeforeGenerateToken: async ( pathname: string /* clientPayload?: string, */ ) => { const session = await getServerSession(authOptions); if (!session?.organization?.id) { throw new Error("Not authorized"); } if (typeof window !== "undefined") { console.log("Window is defined unexpectedly!"); // @ts-ignore window = undefined; } else { console.log("window is not defined"); } return { allowedContentTypes: ["image/jpeg", "image/png", "image/avif", "image/webp"], tokenPayload: JSON.stringify({ organizationId: session.organization.id, }), }; }, onUploadCompleted: async ({ blob, tokenPayload }) => { console.log("blob upload completed", blob.pathname, tokenPayload); }, });
return NextResponse.json(jsonResponse); } catch (error) { console.log("error", error); console.log("error saving images", body); return NextResponse.json( { error: (error as Error).message }, { status: 400 } // The webhook will retry 5 times waiting for a 200 ); }}and here is the client side implementation :
const res = await upload(fileName, imageFile.rawFile, { access: "public", handleUploadUrl: uploadUrl + "/api/images/upload", });Without setting windows to undefined if it is defined I got the following error : "Vercel Blob: "generateClientTokenFromReadWriteToken" must be called from a server environment"
After checking the /blob code, i found a check on window in generateClientTokenFromReadWriteToken() function. So, even if I do not know why window is randomly defined hence I don't think to use any library on server side which create the window variable, I tried to set it to undefined. But after that I got the error : "window is not defined"
How this error could be thrown ?
Is any of you have been confronted to this issue ? Do you have any clue ?
I use the latest /blob realease.