invoke-ai/InvokeAI · error · ExternalProviderRequestError

Seedream response payload missing image data

Error message

Seedream response payload missing image data

What it means

The Seedream external image-generation provider requires its HTTP response JSON to contain a top-level "data" array holding generated image objects. This error is raised when the response parsed as JSON but either omits "data" or has it as a non-list value (null, string, object). It signals that the provider's response shape does not match the expected API contract, so no images can be extracted.

Solutions

  1. Verify the Seedream API key and account status so the provider returns a success payload rather than a JSON error object without "data"
  2. Log the raw response body before parsing to confirm the actual payload shape and compare against the expected {"data": [...]} schema
  3. Check the configured endpoint/model ID matches the Seedream API version in use (schema drift between versions)
  4. Check for a proxy or gateway substituting its own JSON error responses

Example fix

// before
body = response.json()
data_items = body.get("data")
// after
body = response.json()
if "error" in body:
    raise ExternalProviderRequestError(f"Seedream API error: {body['error']}")
data_items = body.get("data")
Defensive patterns

Strategy: type-guard

Validate before calling

body = response.json()
if not isinstance(body.get("data"), list):
    raise ValueError(f"Seedream payload missing data array: {body}")

Type guard

def has_data_array(body: object) -> bool:
    return isinstance(body, dict) and isinstance(body.get("data"), list)

Try / catch

try:
    images = provider.generate(request)
except ExternalProviderRequestError as e:
    logger.error(f"Seedream payload invalid: {e}")
    raise HTTPException(502, "Image provider returned an invalid response")

Prevention

When it happens

Trigger: Calling ExternalProvider.generate() with a Seedream model when the provider returns JSON whose body.get("data") is not a list — e.g. an error JSON body like {"error": {...}} without "data", a malformed/proxy response, or an API version whose payload shape changed.

Common situations: Expired or invalid API key causing the provider to return an error object instead of a generation payload; upstream API schema change; a gateway/load balancer returning JSON error pages; wrong model endpoint configured so responses come from a different API version.

Understand the failure class

Background: "invalid response format", "malformed payload", "missing data field": when an API returns 200 but the response shape is wrong — this error's family across 23 libraries.

Related errors


AI-assisted analysis of invoke-ai/InvokeAI@0b6a024f2f (2026-08-29). Data as JSON: /api/errors/d8adf2f54ef760c9. Report an issue: GitHub.

Appendix: source

Thrown at invokeai/app/services/external_generation/providers/seedream.py:120

            if response.status_code == 429:
                retry_after = _parse_retry_after(response.headers.get("retry-after"))
                raise ExternalProviderRateLimitError(
                    f"Seedream rate limit exceeded. {f'Retry after {retry_after:.0f}s.' if retry_after else 'Please try again later.'}",
                    retry_after=retry_after,
                )
            raise ExternalProviderRequestError(
                f"Seedream request failed with status {response.status_code}: {response.text}"
            )

        body = response.json()
        if not isinstance(body, dict):
            raise ExternalProviderRequestError("Seedream response payload was not a JSON object")

        generated_images: list[ExternalGeneratedImage] = []
        item_errors: list[dict[str, object]] = []
        data_items = body.get("data")
        if not isinstance(data_items, list):
            raise ExternalProviderRequestError("Seedream response payload missing image data")

        for item in data_items:
            if not isinstance(item, dict):
                continue
            # Items may be error objects for failed images in batch — collect rather than discard
            # so partial-failure causes (e.g., content filter) are visible to the caller.
            if "error" in item:
                error_payload = item["error"]
                item_errors.append(
                    error_payload if isinstance(error_payload, dict) else {"message": str(error_payload)}
                )
                continue
            encoded = item.get("b64_json")
            if not encoded:
                continue
            image = decode_image_base64(encoded)
            generated_images.append(ExternalGeneratedImage(image=image, seed=request.seed))

View on GitHub (pinned to 0b6a024f2f)