BerriAI/litellm · error · BlackForestLabsError
BFL initial request failed
Error message
BFL initial request failed: {initial_response.text} What it means
In the sync BFL polling flow, the initial generation POST returned an HTTP status >= 400 and the handler re-raises it verbatim as BlackForestLabsError with the upstream status code and body text. Unlike 'Request failed', this is a real HTTP response from BFL (or whatever serves your base_url), so the status code and body carry the diagnosis (401 bad key, 422 bad params, 429 rate limit, 404 wrong endpoint/model).
Solutions
- Match the status code: 401/403 -> fix BFL_API_KEY / plan access; 422 -> fix request params per the BFL API docs; 429 -> slow down or add retries with backoff; 404 -> fix base_url/model id.
- Print the full message body - BFL includes a human-readable reason in the JSON it returns.
- Confirm the key works directly: `curl -H "x-key: $BFL_API_KEY" https://api.bfl.ai/v1/...`.
- Check your BFL account credits/billing if generation previously worked.
Example fix
# before: model id typo / unsupported params resp = litellm.image_generation(model="flux-pro-1.5", width=123, height=456, prompt="sunset") # after: valid model + allowed dimensions resp = litellm.image_generation(model="flux-pro-1.1", width=1024, height=768, prompt="sunset")
Defensive patterns
Strategy: try-catch
Validate before calling
import os, urllib.request, json
def bfl_key_valid(key: str) -> bool:
req = urllib.request.Request(
"https://api.bfl.ai/v1/flux-pro-1.1", # lightweight endpoint per BFL docs
headers={"x-key": key, "Content-Type": "application/json"},
method="POST", data=json.dumps({"prompt": "ping"}).encode(),
)
try:
urllib.request.urlopen(req, timeout=10)
return True
except urllib.error.HTTPError as e:
return e.code not in (401, 403) # 422/429 still means the key is accepted
except Exception:
return False
assert bfl_key_valid(os.environ["BFL_API_KEY"]) or warn("BFL key rejected") Try / catch
from litellm.llms.black_forest_labs.common_utils import BlackForestLabsError
try:
resp = litellm.image_generation(model="flux-pro-1.1", prompt=p)
except BlackForestLabsError as e:
if e.status_code in (401, 403):
rotate_bfl_key() # auth path
elif e.status_code == 422:
fix_request_params(e) # body names the bad field
elif e.status_code == 429:
schedule_retry_backoff(e)
else:
raise Prevention
- Fail fast on missing BFL_API_KEY at startup rather than at first request.
- Validate model-specific params (width/height/aspect_ratio) against BFL docs before sending.
- Branch handling on status_code - auth, validation, and rate limit need different responses.
When it happens
Trigger: Invalid or revoked BFL API key (401/403); wrong model name like `flux-pro-1.2-ultra` when the account lacks access (403/404); malformed request params - bad aspect_ratio, width/height not in allowed set (422); exceeding credits or rate limits (429); custom base_url missing the `/v1` prefix producing 404.
Common situations: New integration with an unset/expired BFL_API_KEY env var; copy-pasting a model id from BFL docs that the key's plan doesn't cover; passing width/height values BFL doesn't support; free-tier credit exhaustion during a demo; base_url configured without the correct path.
Related errors
- BFL error
- Error parsing BFL response
- Error parsing initial response
- Image generation failed
- Max recursion depth reached while reading image bytes for…
AI-assisted analysis of BerriAI/litellm@77b7c6c40c (2026-08-18).
Data as JSON: /api/errors/a55737b42b82e6ce.
Report an issue: GitHub.
Appendix: source
Thrown at litellm/llms/black_forest_labs/image_generation/handler.py:301
litellm_params=litellm_params_dict,
encoding=None,
)
def _poll_for_result_sync(
self,
initial_response: httpx.Response,
headers: dict,
sync_client: HTTPHandler,
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 (sync version).
"""
# Validate initial response status code
if initial_response.status_code >= 400:
raise BlackForestLabsError(
status_code=initial_response.status_code,
message=f"BFL initial request failed: {initial_response.text}",
)
# Parse initial response to get polling URL
try:
response_data: Final = initial_response.json()
except Exception as e:
raise BlackForestLabsError(
status_code=initial_response.status_code,
message=f"Error parsing initial response: {e}",
)
# Check for immediate errors
if "errors" in response_data:
raise BlackForestLabsError(
status_code=initial_response.status_code,
message=f"BFL error: {response_data['errors']}",View on GitHub (pinned to 77b7c6c40c)