{"record":{"id":"61423a1bddf5c4cd","repo":"affaan-m/ECC","slug":"no-image-url-in-response-from-endpoints-text-to-image-61423a","errorCode":null,"errorMessage":"no image URL in response from {ENDPOINTS['text_to_image']}","messagePattern":"no image URL in response from (.+?)","errorType":"exception","errorClass":"FalError","httpStatus":null,"severity":"error","filePath":"skills/taste-distillation/scripts/taste/falapi.py","lineNumber":622,"sourceCode":"def quantize_duration(duration: float, lo: int = 3, hi: int = 12) -> int:\n    \"\"\"Round a planned shot length onto the video model's supported grid.\"\"\"\n    return int(max(lo, min(hi, round(float(duration)))))\n\n\ndef text_to_image(\n    prompt: str,\n    image_refs: list[str] | None = None,\n    *,\n    timeout: int = 300,\n) -> list[str]:\n    \"\"\"Generate stills, optionally conditioned on reference images.\"\"\"\n    payload: dict[str, Any] = {\"prompt\": prompt, \"num_images\": 1}\n    if image_refs:\n        payload[\"image_urls\"] = list(image_refs)\n    result = submit(ENDPOINTS[\"text_to_image\"], payload, timeout)\n    urls = parse_urls(result)\n    if not urls:\n        raise FalError(f\"no image URL in response from {ENDPOINTS['text_to_image']}\")\n    return urls\n\n\ndef extract_frame(video_url: str, timestamp: float, *, timeout: int = 300) -> str:\n    \"\"\"Pull a single frame out of a hosted video. Returns the image URL.\"\"\"\n    payload = {\"video_url\": video_url, \"timestamp\": round(float(timestamp), 3)}\n    result = submit(ENDPOINTS[\"extract_frame\"], payload, timeout)\n    return first_url(result, ENDPOINTS[\"extract_frame\"])\n\n\ndef compose(tracks: list[dict], *, timeout: int = 900) -> str:\n    \"\"\"Composite timeline tracks into one video. Returns the output URL.\n\n    ``tracks`` is passed straight through so the caller owns the timeline\n    shape; the ffmpeg-api track schema is another default worth verifying\n    before a live run.\n    \"\"\"\n    result = submit(ENDPOINTS[\"compose\"], {\"tracks\": tracks}, timeout)","sourceCodeStart":604,"sourceCodeEnd":640,"githubUrl":"https://github.com/affaan-m/ECC/blob/8321021c54d670126ce3b2969d5deb880b4b0c2a/skills/taste-distillation/scripts/taste/falapi.py#L604-L640","documentation":"FalError raised by text_to_image() after submit() returns a result from which parse_urls() extracts no image URLs. It names the failing endpoint so you know which model's response was malformed. One image is requested (num_images=1), so an empty URL list means the provider did not return the expected output.","triggerScenarios":"text_to_image(prompt, ...) where the fal response lacks its image output field — provider response-shape change, content-policy rejection returning an error object, or model failure.","commonSituations":"Prompt tripped a provider safety filter and the endpoint returned no images; fal.ai updated the model's output schema; transient provider error surfaced as an empty result.","solutions":["Log the raw result dict to inspect what the endpoint actually returned","Rephrase the prompt if a content policy rejection is suspected and retry","Check the fal.ai model page for the endpoint's current response schema and update parsing","Wrap submit/parse in a retry for transient provider failures"],"exampleFix":"// before\nurls = falapi.text_to_image(prompt)  # FalError: no image URL in response\n// after\ntry:\n    urls = falapi.text_to_image(prompt)\nexcept falapi.FalError:\n    result = falapi.submit(falapi.ENDPOINTS[\"text_to_image\"], {\"prompt\": prompt, \"num_images\": 1})\n    raise RuntimeError(f\"text_to_image returned no URLs; keys={list(result) if isinstance(result, dict) else type(result)}\")","handlingStrategy":"retry","validationCode":"result = falapi.submit(falapi.ENDPOINTS[\"text_to_image\"], {\"prompt\": prompt, \"num_images\": 1})\nassert falapi.parse_urls(result), f\"no image URLs; keys={list(result) if isinstance(result, dict) else type(result)}\"","typeGuard":null,"tryCatchPattern":"try:\n    urls = falapi.text_to_image(prompt)\nexcept falapi.FalError:\n    prompt = sanitize_prompt(prompt)  # may have tripped content policy\n    urls = falapi.text_to_image(prompt)","preventionTips":["Log raw provider responses in dev to spot schema changes early","Rephrase prompts that may trigger content filters","Add a retry with backoff around text_to_image for transient provider issues","Track the fal.ai model version; update parsing when the schema changes"],"tags":["python","api","response-shape","text-to-image"],"backgroundTag":"unexpected-api-response-shape","analyzedSha":"8321021c54d670126ce3b2969d5deb880b4b0c2a","analyzedAt":"2026-09-16T10:08:13.343Z","contentChangedAt":"2026-09-16T10:08:13.343Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}