From e5814b12c6253d952c9cb9ebaf4671a56656d650 Mon Sep 17 00:00:00 2001 From: Jeff Emmett Date: Mon, 16 Mar 2026 20:51:05 -0700 Subject: [PATCH] fix(rsplat): use fal.ai response_url for result fetch, add poll logging The result fetch was constructing its own URL instead of using the response_url returned by fal.ai's status poll. This caused 422 errors. Now captures response_url from poll and uses it for result retrieval. Co-Authored-By: Claude Opus 4.6 --- server/index.ts | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/server/index.ts b/server/index.ts index 1c7f369..4da1324 100644 --- a/server/index.ts +++ b/server/index.ts @@ -790,6 +790,7 @@ async function process3DGenJob(job: Gen3DJob) { // 3. Poll for completion (up to 8 min — Hunyuan3D with textures can take 3-5 min) const deadline = Date.now() + 480_000; + let responseUrl = ""; let completed = false; while (Date.now() < deadline) { await new Promise((r) => setTimeout(r, 3000)); @@ -798,9 +799,11 @@ async function process3DGenJob(job: Gen3DJob) { { headers: falHeaders }, ); if (!statusRes.ok) continue; - const status = await statusRes.json() as { status: string }; - if (status.status === "COMPLETED") { completed = true; break; } - if (status.status === "FAILED") { + const statusData = await statusRes.json() as { status: string; response_url?: string }; + console.log(`[3d-gen] Poll ${job.id}: status=${statusData.status}`); + if (statusData.response_url) responseUrl = statusData.response_url; + if (statusData.status === "COMPLETED") { completed = true; break; } + if (statusData.status === "FAILED") { job.status = "failed"; job.error = "3D generation failed on fal.ai"; job.completedAt = Date.now(); @@ -814,20 +817,16 @@ async function process3DGenJob(job: Gen3DJob) { return; } - // 4. Fetch result (retry once after 3s on transient failure) - let resultRes = await fetch( - `https://queue.fal.run/${MODEL}/requests/${request_id}`, - { headers: falHeaders }, - ); + // 4. Fetch result using response_url from status (with fallback) + const resultUrl = responseUrl || `https://queue.fal.run/${MODEL}/requests/${request_id}`; + console.log(`[3d-gen] Fetching result from: ${resultUrl}`); + let resultRes = await fetch(resultUrl, { headers: falHeaders }); if (!resultRes.ok) { console.warn(`[3d-gen] Result fetch failed (status=${resultRes.status}), retrying in 3s...`); const errBody = await resultRes.text().catch(() => ""); console.warn(`[3d-gen] Result error body:`, errBody); await new Promise((r) => setTimeout(r, 3000)); - resultRes = await fetch( - `https://queue.fal.run/${MODEL}/requests/${request_id}`, - { headers: falHeaders }, - ); + resultRes = await fetch(resultUrl, { headers: falHeaders }); } if (!resultRes.ok) { const errBody = await resultRes.text().catch(() => "");