BerriAI/litellm · error · BlackForestLabsError
Polling timed out after
Error message
Polling timed out after {max_wait} seconds What it means
Sync BFL polling exceeded `max_wait` (default DEFAULT_MAX_POLLING_TIME = 300 seconds) without the task reaching `Ready` or any terminal status, so the handler raises BlackForestLabsError(408). BFL generation is asynchronous - LiteLLM submits, then polls every ~1.5s - and heavily loaded queues can legitimately take longer than the 5-minute budget.
Solutions
- Retry the call - if the queue was merely slow, a resubmission often completes within budget.
- Reduce load: lower concurrency per API key, or spread submissions over time.
- If you control the handler call, pass a larger max_wait/polling budget where the plumbing exposes it, or wrap with your own retry-with-backoff.
- Check BFL status for incidents when timeouts cluster across many jobs.
Example fix
# before
resp = litellm.image_generation(model="flux-pro-1.1-ultra", prompt=very_complex_prompt)
# after: retry with backoff for slow queues
import time
for attempt in range(3):
try:
resp = litellm.image_generation(model="flux-pro-1.1-ultra", prompt=very_complex_prompt)
break
except Exception as e:
if getattr(e, "status_code", None) == 408 and attempt < 2:
time.sleep(10 * (attempt + 1))
continue
raise Defensive patterns
Strategy: retry
Try / catch
from litellm.llms.black_forest_labs.common_utils import BlackForestLabsError
for attempt in range(3):
try:
resp = litellm.image_generation(model="flux-pro-1.1", prompt=p)
break
except BlackForestLabsError as e:
if e.status_code == 408 and attempt < 2:
time.sleep(15 * (attempt + 1)) # queue was slow; resubmit
continue
raise Prevention
- Budget for the 300s default polling window in your own caller timeouts.
- Lower per-key concurrency so jobs spend less time queued.
- Treat 408 as retryable but cap retries to avoid duplicating paid generations.
When it happens
Trigger: Peak-hour queue backlog on BFL pushing a job past 300s; very slow settings (max prompts / high resolution / upscale-heavy models like flux-pro-1.1-ultra); many concurrent submissions from one key serializing server-side; the task stuck in `Queued`/`Processing` indefinitely after a platform incident.
Common situations: Batch generation jobs during evening load; single-threaded workers that submit several images in sequence, each nearing the budget; LiteLLM proxy setups where callers expect the OpenAI-style synchronous feel and time out at their own layer too.
Understand the failure class
- Timeouts: ETIMEDOUT, deadlines, and hung requests — what actually expires when a request times out.
Related errors
- Polling failed
- Error parsing initial response
- Image generation failed
- No polling_url in BFL response
- Request failed
AI-assisted analysis of BerriAI/litellm@77b7c6c40c (2026-08-18).
Data as JSON: /api/errors/1807616f72ffd114.
Report an issue: GitHub.
Appendix: source
Thrown at litellm/llms/black_forest_labs/image_generation/handler.py:373
verbose_logger.debug("BFL poll status: %s", status)
if status == "Ready":
return response
elif status in [
"Error",
"Failed",
"Content Moderated",
"Request Moderated",
]:
raise BlackForestLabsError(
status_code=400,
message=f"Image generation failed: {status}",
)
time.sleep(interval)
raise BlackForestLabsError(
status_code=408,
message=f"Polling timed out after {max_wait} seconds",
)
async def _poll_for_result_async(
self,
initial_response: httpx.Response,
headers: dict,
async_client: AsyncHTTPHandler,
max_wait: float = DEFAULT_MAX_POLLING_TIME,
interval: float = DEFAULT_POLLING_INTERVAL,
timeout: float | httpx.Timeout | None = None,
) -> httpx.Response:
"""
Poll BFL API until result is ready (async version).
"""
# Validate initial response status code
if initial_response.status_code >= 400:View on GitHub (pinned to 77b7c6c40c)