decolua/9router · error

NanoBanana generation failed

Error message

NanoBanana generation failed

What it means

Thrown when the NanoBanana poll endpoint reports the generation task itself failed: the successFlag field comes back 2 or 3 (failure codes). The error message is the provider's own s.data.errorMessage when present, falling back to this generic string. Unlike [50], the HTTP call succeeded — the upstream task genuinely failed.

Source

Thrown at open-sse/handlers/imageProviders/nanobanana.js:51

    }
    return req;
  },
  // Async: parse submit → poll until SUCCESS, return raw poll data
  async parseResponse(response, { headers }) {
    const submitData = await response.json();
    if (submitData.code !== 200) throw new Error(submitData.msg || "NanoBanana submit failed");
    const taskId = submitData.data?.taskId;
    if (!taskId) throw new Error("NanoBanana: no taskId returned");
    const pollUrl = `${POLL_BASE}?taskId=${encodeURIComponent(taskId)}`;
    const deadline = Date.now() + POLL_TIMEOUT_MS;
    while (Date.now() < deadline) {
      await sleep(POLL_INTERVAL_MS);
      const r = await fetch(pollUrl, { headers });
      if (!r.ok) throw new Error(`NanoBanana status ${r.status}`);
      const s = await r.json();
      const flag = s.data?.successFlag;
      if (flag === 1) return s.data;
      if (flag === 2 || flag === 3) throw new Error(s.data?.errorMessage || "NanoBanana generation failed");
    }
    throw new Error("NanoBanana polling timeout");
  },
  normalize: (responseBody, prompt) => {
    const url = responseBody.response?.resultImageUrl || responseBody.response?.originImageUrl;
    if (url) return { created: nowSec(), data: [{ url, revised_prompt: prompt }] };
    return { created: nowSec(), data: [] };
  },
};

View on GitHub (pinned to 90b52e06ff)

Solutions

  1. Log/inspect the full poll response to read s.data.errorMessage — the thrown Error already carries it when the provider supplies one.
  2. If the message is the generic fallback, re-run with a simpler/safer prompt to rule out moderation rejection.
  3. For edit requests, verify every URL in imageUrls/body.image is publicly fetchable and a supported format (png/jpeg).
  4. Retry once with a fresh submit — transient upstream capacity failures are common with this async API.
  5. Check numImages (body.n) and image_size/ratio values against the provider's supported ranges.

Example fix

// before (caller has no provider detail when errorMessage is absent)
const flag = s.data?.successFlag;
if (flag === 2 || flag === 3) throw new Error(s.data?.errorMessage || "NanoBanana generation failed");
// after
const flag = s.data?.successFlag;
if (flag === 2 || flag === 3) throw new Error(s.data?.errorMessage || `NanoBanana generation failed (successFlag=${flag}, taskId=${taskId})`);
Defensive patterns

Strategy: try-catch

Validate before calling

// Validate the request before submitting to reduce upstream task failures
if (!body.prompt || !body.prompt.trim()) throw new Error("prompt is required");
const urls = [body.image, ...(Array.isArray(body.images) ? body.images : [])].filter(Boolean);
for (const u of urls) {
  if (!/^https?:\/\//.test(u)) throw new Error(`image URL must be http(s): ${u}`);
}

Type guard

function isPollResult(s) { return !!s && typeof s === "object" && s.data != null && typeof s.data.successFlag === "number"; }
// then: if (isPollResult(s) && (s.data.successFlag === 2 || s.data.successFlag === 3)) -> failed

Try / catch

try {
  const data = await imageProvider.parseResponse(response, { headers });
} catch (e) {
  if (e.message === "NanoBanana generation failed" || /NanoBanana/.test(e.message)) {
    console.error("NanoBanana task failed:", e.message); // e.message may carry provider errorMessage
    return { error: { code: "generation_failed", detail: e.message } }; // surface to client instead of crashing
  }
  throw e;
}

Prevention

When it happens

Trigger: During polling in open-sse/handlers/imageProviders/nanobanana.js:49-51, the poll JSON satisfies `s.data?.successFlag === 2 || s.data?.successFlag === 3`. The thrown message equals `s.data?.errorMessage` when provided, otherwise the literal 'NanoBanana generation failed'.

Common situations: Prompt rejected by upstream content moderation; image edit requests (type IMAGETOIAMGE) with unreachable or rejected imageUrls; invalid numImages/ratio combos; upstream GPU capacity failures; generic 'generation failed' because the provider returns successFlag 2/3 with no errorMessage.

Related errors


AI-assisted analysis of decolua/9router@90b52e06ff (2026-08-30). Data as JSON: /api/errors/4a662a6bc3f20c91. Report an issue: GitHub.