invoke-ai/InvokeAI · error · ExternalProviderRequestError

DashScope response missing output

Error message

DashScope response missing output: {data}

What it means

The AlibabaCloud DashScope provider calls _parse_sync_response after a synchronous multimodal-generation request. It expects the JSON body to contain an 'output' object (the standard DashScope envelope). If 'output' is absent or not a dict, the provider cannot extract choices/images and raises ExternalProviderRequestError to surface the malformed response (with the raw data) to the caller.

Solutions

  1. Log the full response body in the message to identify what DashScope actually returned (the error already embeds {data})
  2. Verify external_alibabacloud_base_url points at the correct DashScope endpoint (e.g. https://dashscope-intl.aliyuncs.com) and not a proxy that alters payloads
  3. Confirm the model_id is in _SYNC_MODELS so the sync endpoint is the right API for that model
  4. Check DashScope account status/quota — some throttled/failed responses come back 200 with a non-standard body
  5. Upgrade InvokeAI in case the provider was updated for a DashScope schema change

Example fix

# before
output = data.get("output")
if not isinstance(output, dict):
    raise ExternalProviderRequestError(f"DashScope response missing output: {data}")
# after
output = data.get("output")
if output is None and isinstance(data.get("code"), str):
    raise ExternalProviderRequestError(
        f"DashScope API error {data.get('code')}: {data.get('message')}"
    )
if not isinstance(output, dict):
    raise ExternalProviderRequestError(f"DashScope response missing output: {data}")
Defensive patterns

Strategy: type-guard

Validate before calling

import requests
def precheck(base_url: str, api_key: str) -> None:
    r = requests.get(f"{base_url.rstrip('/')}/api/v1/models", headers={"Authorization": f"Bearer {api_key}"}, timeout=10)
    r.raise_for_status()

Type guard

def has_output(data: dict) -> bool:
    return isinstance(data.get("output"), dict)

Try / catch

try:
    result = provider.generate(request)
except ExternalProviderRequestError as e:
    if "missing output" in str(e):
        log.error("DashScope returned a non-standard envelope: %s", e)
    raise

Prevention

When it happens

Trigger: POST to /api/v1/services/aigc/multimodal-generation/generation returns 200 but the JSON body lacks an 'output' key, or 'output' is null/list/string — e.g. an API error body, a proxy/WAF HTML or JSON error page, or a DashScope schema change.

Common situations: Using a custom external_alibabacloud_base_url pointing at a gateway that rewrites responses; DashScope returning an error envelope with only 'code'/'message' while still returning HTTP 200; region mismatch (dashscope-intl vs dashscope.cn endpoints) returning unexpected bodies; API version drift.

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/9d3e285015d2187c. Report an issue: GitHub.

Appendix: source

Thrown at invokeai/app/services/external_generation/providers/alibabacloud.py:221

            if status == "SUCCEEDED":
                return self._parse_async_response(output, request, request_id)
            if status in ("FAILED", "UNKNOWN"):
                message = output.get("message", "Unknown error")
                raise ExternalProviderRequestError(f"DashScope task {task_id} failed: {message}")

            self._logger.debug("DashScope task %s status: %s (%.0fs elapsed)", task_id, status, elapsed)
            time.sleep(_TASK_POLL_INTERVAL)

    def _parse_sync_response(
        self,
        data: dict[str, object],
        request: ExternalGenerationRequest,
        request_id: str | None,
    ) -> ExternalGenerationResult:
        """Parse the synchronous multimodal-generation response."""
        output = data.get("output")
        if not isinstance(output, dict):
            raise ExternalProviderRequestError(f"DashScope response missing output: {data}")

        choices = output.get("choices")
        if not isinstance(choices, list):
            raise ExternalProviderRequestError(f"DashScope response missing choices: {data}")

        images: list[ExternalGeneratedImage] = []
        for choice in choices:
            if not isinstance(choice, dict):
                continue
            message = choice.get("message")
            if not isinstance(message, dict):
                continue
            content = message.get("content")
            if not isinstance(content, list):
                continue
            for part in content:
                if not isinstance(part, dict):
                    continue

View on GitHub (pinned to 0b6a024f2f)