BerriAI/litellm · error · BlackForestLabsError
Polling failed: {response.text}
Error message
Polling failed: {response.text} What it means
During the sync polling loop, each GET to the polling_url must return 200. A single non-200 poll (auth expiry mid-poll, 429 throttling, 5xx blips, or the polling URL expiring) aborts the loop and re-raises with the upstream status and body. The job may or may not still be running on BFL's side.
Source
Thrown at litellm/llms/black_forest_labs/image_generation/handler.py:348
# BFL uses regional subdomains (e.g. gateway.bfl.ai) that differ from the
# submission host (api.bfl.ai), so we validate against the registered
# domain rather than doing a strict same-origin check. VERIA-51.
assert_bfl_polling_url(polling_url)
# Get just the auth header for polling
polling_headers: Final = {"x-key": headers.get("x-key", "")}
start_time: Final = time.time()
verbose_logger.debug("BFL starting sync polling at %s", polling_url)
while time.time() - start_time < max_wait:
response = sync_client.get(
url=polling_url,
headers=polling_headers,
)
if response.status_code != 200:
raise BlackForestLabsError(
status_code=response.status_code,
message=f"Polling failed: {response.text}",
)
data = response.json()
status = data.get("status")
verbose_logger.debug("BFL poll status: %s", status)
if status == "Ready":
return response
elif status in [
"Error",
"Failed",
"Content Moderated",
"Request Moderated",
]:
raise BlackForestLabsError(View on GitHub (pinned to 6c2dcb801b)
Solutions
- Read the embedded response body — 429 means back off (raise interval), 404 means the job/URL expired (resubmit), 5xx means retry the whole call once.
- Increase the polling interval so BFL is not throttling you.
- For 401, verify the key is still valid; keys rotated mid-job kill polling auth.
- Resubmit the generation — a dead polling session cannot be resumed through this API.
Defensive patterns
Strategy: retry
Validate before calling
null
Type guard
null
Try / catch
from litellm.exceptions import APIError
try:
img = litellm.image_generation(model=M, prompt=p)
except APIError as e:
sc = getattr(e, "status_code", None)
if sc == 429:
increase_interval_and_retry()
elif sc == 404:
return litellm.image_generation(model=M, prompt=p) # URL expired -> resubmit
elif sc and sc >= 500:
return litellm.image_generation(model=M, prompt=p)
raise Prevention
- Poll at or above the default interval — faster polling invites 429s.
- Don't rotate BFL keys while jobs are in flight; polling auth uses the submission key.
- Resubmit rather than resume: expired polling URLs are not recoverable.
When it happens
Trigger: Any poll response != 200 during the window: 401 if the key is invalidated mid-job, 429 when polling faster than BFL tolerates, 404 when the polling_url expires or the job record ages out, 5xx transient gateway errors.
Common situations: Aggressive polling intervals combined with BFL throttling; long-running jobs whose polling URLs expire; key rotation during an in-flight job; BFL incidents.
Related errors
- BFL initial request failed: {initial_response.text}
- No polling_url in BFL response
- Image generation failed: {status}
- Polling timed out after {max_wait} seconds
- err.response.text
AI-assisted analysis of BerriAI/litellm@6c2dcb801b (2026-08-15).
Data as JSON: /api/errors/8fc65448f2699b75.
Report an issue: GitHub.