{"record":{"id":"4a933c8c433097ea","repo":"moeru-ai/airi","slug":"no-image-data-returned-from-nano-banana","errorCode":null,"errorMessage":"No image data returned from Nano Banana","messagePattern":"No image data returned from Nano Banana","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"apps/stage-tamagotchi/src/main/services/airi/widgets/providers/nanobanana.ts","lineNumber":96,"sourceCode":"        }),\n      })\n\n      const json = await response.json()\n      if (json.error) {\n        throw new Error(json.error.message || 'Nano Banana API Error')\n      }\n\n      // Search all parts for the first image\n      const responseParts = json.candidates?.[0]?.content?.parts || []\n      const imagePart = responseParts.find((p: any) => p.inlineData?.data)\n      const inlineData = imagePart?.inlineData\n\n      if (inlineData?.data) {\n        const dataUrl = `data:${inlineData.mimeType};base64,${inlineData.data}`\n        this.updateStatus(jobId, { status: 'succeeded', progress: 100, imageUrl: dataUrl })\n      }\n      else {\n        throw new Error('No image data returned from Nano Banana')\n      }\n    }\n    catch (e: any) {\n      log.error(`[Nano Banana] Generation failed: ${e.message}`)\n      this.updateStatus(jobId, { status: 'failed', error: e.message })\n    }\n    finally {\n      // Clean up callback and job result after completion to prevent memory leaks\n      setTimeout(() => {\n        this.callbacks.delete(jobId)\n        this.jobResults.delete(jobId)\n      }, 10000)\n    }\n  }\n\n  async getStatus(jobId: string): Promise<ArtistryJobStatus> {\n    return this.jobResults.get(jobId) || { status: 'queued' }\n  }","sourceCodeStart":78,"sourceCodeEnd":114,"githubUrl":"https://github.com/moeru-ai/airi/blob/27111382b4a79a7e983289d6e983a06af185ed0f/apps/stage-tamagotchi/src/main/services/airi/widgets/providers/nanobanana.ts#L78-L114","documentation":"Thrown by the Nano Banana provider when the API response parsed successfully and contained no error, but no candidate part with inlineData.data was found. The provider searches candidates[0].content.parts for the first part with inlineData.data; if none exists, it cannot extract an image.","triggerScenarios":"The API returned a valid response (no error field) but the candidates content was empty, contained only text parts, or the image was filtered/omitted — e.g. the model returned a textual refusal instead of an image, or the response shape differed from expectations.","commonSituations":"The model returned a safety refusal as text (no image); the requested model variant doesn't output inline image data; prompt engineering produced a non-image response; API version changed the part schema; candidates array was empty.","solutions":["Log the full responseParts to see what the model actually returned (text refusal, empty, etc.).","Adjust the prompt to request an image explicitly and avoid content that triggers a text-only refusal.","Confirm the configured model outputs inlineData image parts (not all Gemini variants do).","Handle a text-only response gracefully in the caller rather than treating it as a hard failure."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// Inspect response parts before assuming an image\nconst parts = json.candidates?.[0]?.content?.parts ?? []\nconst hasImage = parts.some((p: any) => p.inlineData?.data)\nif (!hasImage) {\n  // log parts to see if it's a text refusal\n  throw new Error('No image in Nano Banana response; model may have refused')\n}","typeGuard":"function hasInlineImage(parts: any[]): boolean {\n  return Array.isArray(parts) && parts.some(p => p?.inlineData?.data)\n}","tryCatchPattern":"try {\n  return await provider.generate(request)\n} catch (e) {\n  if (/No image data returned/.test(errorMessageFrom(e) ?? '')) {\n    return { error: 'Nano Banana returned no image (possible refusal)' }\n  }\n  throw e\n}","preventionTips":["Log responseParts to detect text refusals vs empty responses.","Use a model variant confirmed to emit inlineData image parts.","Craft prompts that clearly request image output to avoid text-only replies."],"tags":["nanobanana","artistry","api","providers","validation"],"backgroundTag":null,"analyzedSha":"27111382b4a79a7e983289d6e983a06af185ed0f","analyzedAt":"2026-08-12T18:33:34.132Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}