affaan-m/ECC · error · FalError
no URL in provider response; response shape may have…
Error message
no URL in provider response; response shape may have changed (provider payload omitted)
What it means
falapi.parse_urls found no downloadable asset URL in the JSON returned by a fal.ai endpoint, so first_url cannot return a result and raises FalError. The library treats this as a sign that the provider's response schema changed or the model produced no output. It is a defensive guard against silently returning an empty/None URL to callers like _mesh_url, retopologize, split_parts, images_to_video, reference_to_video, and extract_frame.
Solutions
- Print/log the raw provider response (result) to inspect the actual keys and find where the URL now lives
- Check fal.ai docs/changelog for the endpoint used in ENDPOINTS and update parse_urls to the new response shape
- Retry the generation — transient model failures can return an empty payload; also verify the input passed safety/size checks
- Pin the model endpoint version on fal.ai so schema changes don't silently break the client
Example fix
// before
url = first_url(result, ENDPOINTS['images_to_video'])
// after
urls = parse_urls(result)
if not urls:
print(json.dumps(result, indent=2)) # inspect real payload keys
raise FalError('images_to_video returned no URL; inspect payload above') Defensive patterns
Strategy: try-catch
Validate before calling
urls = parse_urls(result)
if not urls:
# decide fallback before calling first_url
... Type guard
def has_urls(result) -> bool:
return bool(parse_urls(result)) Try / catch
try:
url = first_url(result, endpoint)
except FalError:
logger.warning('no asset URL for %s; retrying', endpoint)
url = first_url(submit(endpoint, payload, timeout), endpoint) # one retry Prevention
- Log the raw provider payload on every wrapper call for post-mortems
- Pin fal.ai model endpoint versions to avoid silent schema drift
- Add a unit test asserting parse_urls against a captured real response
- Treat empty generations (content-filter rejections) as an expected case in pipeline code
When it happens
Trigger: Any wrapper call (_mesh_url, retopologize, split_parts, images_to_video, reference_to_video, extract_frame, merge_videos) whose fal.ai endpoint returns 200 with a payload containing no URL fields (e.g. missing 'video_url'/'image_url'/'mesh_url' keys), an empty output object, or a qualitatively failed generation that still reports success.
Common situations: fal.ai changes an endpoint's response schema after a model upgrade; the queue request succeeded but the model returned no artifact (e.g. safety filter rejected the generation); calling extract_frame with a timestamp beyond the video length; an API version mismatch between the client payload and the deployed model.
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
- no image URL in response from
- fal call failed after one attempt; job acceptance may be…
- fal call failed after one attempt; job acceptance may be…
- fal upload failed; provider details omitted
- fal upload failed; provider details omitted
AI-assisted analysis of affaan-m/ECC@8321021c54 (2026-09-16).
Data as JSON: /api/errors/8e4fa96b9b5a40db.
Report an issue: GitHub.
Appendix: source
Thrown at skills/taste-application/scripts/taste/falapi.py:370
elif isinstance(node, dict):
if isinstance(node.get("url"), str):
found.append(node["url"])
for k, v in node.items():
if k != "url":
walk(v)
elif isinstance(node, (list, tuple)):
for v in node:
walk(v)
walk(result)
seen: set[str] = set()
return [u for u in found if not (u in seen or seen.add(u))]
def first_url(result: Any, endpoint: str) -> str:
urls = parse_urls(result)
if not urls:
raise FalError(
"no URL in provider response; response shape may have changed "
"(provider payload omitted)"
)
return urls[0]
def _mesh_url(result: Any, endpoint: str) -> str:
"""The GLB out of a 3D response, addressed by key rather than by position.
``first_url`` would work only as long as ``model_glb`` happens to be the
first URL-bearing key in the response. It is today; the response also
carries a ``thumbnail`` PNG and a ``model_urls`` block with obj/fbx/mtl,
so a key reordering upstream would quietly start returning a preview image
where a mesh is expected - and a preview image downloads fine, so nothing
would fail until Blender refused to open it.
"""
if isinstance(result, dict):
for path in (("model_glb", "url"), ("model_urls", "glb", "url"),View on GitHub (pinned to 8321021c54)