moeru-ai/airi · error · Error

No image data returned from Nano Banana

Error message

No image data returned from Nano Banana

What it means

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.

Source

Thrown at apps/stage-tamagotchi/src/main/services/airi/widgets/providers/nanobanana.ts:96

        }),
      })

      const json = await response.json()
      if (json.error) {
        throw new Error(json.error.message || 'Nano Banana API Error')
      }

      // Search all parts for the first image
      const responseParts = json.candidates?.[0]?.content?.parts || []
      const imagePart = responseParts.find((p: any) => p.inlineData?.data)
      const inlineData = imagePart?.inlineData

      if (inlineData?.data) {
        const dataUrl = `data:${inlineData.mimeType};base64,${inlineData.data}`
        this.updateStatus(jobId, { status: 'succeeded', progress: 100, imageUrl: dataUrl })
      }
      else {
        throw new Error('No image data returned from Nano Banana')
      }
    }
    catch (e: any) {
      log.error(`[Nano Banana] Generation failed: ${e.message}`)
      this.updateStatus(jobId, { status: 'failed', error: e.message })
    }
    finally {
      // Clean up callback and job result after completion to prevent memory leaks
      setTimeout(() => {
        this.callbacks.delete(jobId)
        this.jobResults.delete(jobId)
      }, 10000)
    }
  }

  async getStatus(jobId: string): Promise<ArtistryJobStatus> {
    return this.jobResults.get(jobId) || { status: 'queued' }
  }

View on GitHub (pinned to 27111382b4)

Solutions

  1. Log the full responseParts to see what the model actually returned (text refusal, empty, etc.).
  2. Adjust the prompt to request an image explicitly and avoid content that triggers a text-only refusal.
  3. Confirm the configured model outputs inlineData image parts (not all Gemini variants do).
  4. Handle a text-only response gracefully in the caller rather than treating it as a hard failure.
Defensive patterns

Strategy: validation

Validate before calling

// Inspect response parts before assuming an image
const parts = json.candidates?.[0]?.content?.parts ?? []
const hasImage = parts.some((p: any) => p.inlineData?.data)
if (!hasImage) {
  // log parts to see if it's a text refusal
  throw new Error('No image in Nano Banana response; model may have refused')
}

Type guard

function hasInlineImage(parts: any[]): boolean {
  return Array.isArray(parts) && parts.some(p => p?.inlineData?.data)
}

Try / catch

try {
  return await provider.generate(request)
} catch (e) {
  if (/No image data returned/.test(errorMessageFrom(e) ?? '')) {
    return { error: 'Nano Banana returned no image (possible refusal)' }
  }
  throw e
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of moeru-ai/airi@27111382b4 (2026-08-12). Data as JSON: /api/errors/4a933c8c433097ea. Report an issue: GitHub.