abi/screenshot-to-code · error · ValueError

Prediction ID not found in initial response.

Error message

Prediction ID not found in initial response.

What it means

In the Replicate image-generation client, _extract_prediction_id raises ValueError when the JSON body of the prediction-creation POST response lacks a usable `id` — either the field is missing, not a string, or an empty string. This means Replicate accepted the HTTP request (2xx) but returned a payload that doesn't look like a prediction object, e.g. an error envelope or an API shape change.

Source

Thrown at backend/image_generation/replicate.py:46

DEFAULT_IMAGE_MODEL: ReplicateImageModel = "z_image_turbo"
REMOVE_BACKGROUND_VERSION = (
    "a029dff38972b5fda4ec5d75d7d1cd25aeff621d2cf4946a41055d7db66b80bc"
)
POLL_INTERVAL_SECONDS = 0.1
MAX_POLLS = 100


def _build_headers(api_token: str) -> dict[str, str]:
    return {
        "Authorization": f"Bearer {api_token}",
        "Content-Type": "application/json",
    }


def _extract_prediction_id(response_json: Mapping[str, Any]) -> str:
    prediction_id = response_json.get("id")
    if not isinstance(prediction_id, str) or not prediction_id:
        raise ValueError("Prediction ID not found in initial response.")
    return prediction_id


async def _poll_prediction(
    client: httpx.AsyncClient, prediction_id: str, headers: dict[str, str]
) -> dict[str, Any]:
    status_check_url = f"{REPLICATE_API_BASE_URL}/predictions/{prediction_id}"

    for _ in range(MAX_POLLS):
        await asyncio.sleep(POLL_INTERVAL_SECONDS)
        status_response = await client.get(status_check_url, headers=headers)
        status_response.raise_for_status()
        status_response_raw: Any = status_response.json()
        if not isinstance(status_response_raw, dict):
            raise ValueError("Invalid prediction status response.")
        status_response_json = cast(dict[str, Any], status_response_raw)

        status = status_response_json.get("status")

View on GitHub (pinned to d026163f58)

Solutions

  1. Log the full response body when this fires to see what Replicate actually returned.
  2. Verify model_path is a valid, current Replicate model (owner/name or owner/name:version).
  3. Check REPLICATE_API_BASE_URL is the official API base (https://api.replicate.com) and not being intercepted.
  4. If the API shape changed, update _extract_prediction_id to read the new id field.
Defensive patterns

Strategy: type-guard

Type guard

from typing import Mapping, Any

def has_prediction_id(response_json: Any) -> bool:
    return isinstance(response_json, Mapping) and isinstance(
        response_json.get("id"), str
    ) and bool(response_json["id"])

Try / catch

try:
    result = await call_replicate_model(model, input, token)
except ValueError as e:
    if "Prediction ID not found" in str(e):
        log.error("Replicate returned unexpected envelope: %s", model)
    raise

Prevention

When it happens

Trigger: POST to {REPLICATE_API_BASE_URL}/models/{model_path}/predictions returning 200/201 with a body like {"detail": "..."} or {"id": null} or {"id": 12345} (non-string). Also when a proxy or gateway intercepts the response and returns its own JSON.

Common situations: Replicate API contract change or model endpoint responding with a different envelope; using a model_path that silently redirects; a corporate proxy rewriting responses; version drift between this client and Replicate's current API.

Related errors


AI-assisted analysis of abi/screenshot-to-code@d026163f58 (2026-08-14). Data as JSON: /api/errors/4f7abc549fa7e71b. Report an issue: GitHub.