{"record":{"id":"1807616f72ffd114","repo":"BerriAI/litellm","slug":"polling-timed-out-after-max-wait-seconds-180761","errorCode":null,"errorMessage":"Polling timed out after {max_wait} seconds","messagePattern":"Polling timed out after (.+?) seconds","errorType":"exception","errorClass":"BlackForestLabsError","httpStatus":408,"severity":"error","filePath":"litellm/llms/black_forest_labs/image_generation/handler.py","lineNumber":373,"sourceCode":"\n            verbose_logger.debug(\"BFL poll status: %s\", status)\n\n            if status == \"Ready\":\n                return response\n            elif status in [\n                \"Error\",\n                \"Failed\",\n                \"Content Moderated\",\n                \"Request Moderated\",\n            ]:\n                raise BlackForestLabsError(\n                    status_code=400,\n                    message=f\"Image generation failed: {status}\",\n                )\n\n            time.sleep(interval)\n\n        raise BlackForestLabsError(\n            status_code=408,\n            message=f\"Polling timed out after {max_wait} seconds\",\n        )\n\n    async def _poll_for_result_async(\n        self,\n        initial_response: httpx.Response,\n        headers: dict,\n        async_client: AsyncHTTPHandler,\n        max_wait: float = DEFAULT_MAX_POLLING_TIME,\n        interval: float = DEFAULT_POLLING_INTERVAL,\n        timeout: float | httpx.Timeout | None = None,\n    ) -> httpx.Response:\n        \"\"\"\n        Poll BFL API until result is ready (async version).\n        \"\"\"\n        # Validate initial response status code\n        if initial_response.status_code >= 400:","sourceCodeStart":355,"sourceCodeEnd":391,"githubUrl":"https://github.com/BerriAI/litellm/blob/6c2dcb801bf2b75c18f1bb24140e7cf57465cc4d/litellm/llms/black_forest_labs/image_generation/handler.py#L355-L391","documentation":"The sync polling loop tracks elapsed time and raises 408 once `time.time() - start_time >= max_wait` without the job reaching a terminal status. The BFL job is likely still queued or processing — the client simply gave up first. No cancellation is sent upstream; the result may appear on BFL's side after you stopped asking.","triggerScenarios":"litellm.image_generation (sync) where the job stays in non-terminal statuses (e.g. 'Processing', 'Queued') beyond DEFAULT_MAX_POLLING_TIME, with `time.sleep(interval)` between polls.","commonSituations":"Peak-load queueing on BFL; high-step or large generations; many concurrent jobs on one key; defaults tuned for lighter workloads.","solutions":["Raise the time budget: pass a larger timeout/max_wait via litellm_params or bump DEFAULT_MAX_POLLING_TIME in your fork/deployment.","Lower concurrency per API key so jobs start sooner.","Retry — resubmission after a timeout frequently completes faster than the stuck original.","Pre-warm/tune prompt size and steps so jobs fit the window."],"exampleFix":"# before\nimg = litellm.image_generation(model=\"black_forest_labs/flux-pro-1.1\", prompt=\"...\")\n\n# after\nimg = litellm.image_generation(model=\"black_forest_labs/flux-pro-1.1\", prompt=\"...\", timeout=600)","handlingStrategy":"retry","validationCode":"null","typeGuard":"null","tryCatchPattern":"import time\n\nfor attempt in range(2):\n    try:\n        return litellm.image_generation(model=M, prompt=p, timeout=600)\n    except Exception as e:\n        if getattr(e, \"status_code\", None) == 408 and attempt == 0:\n            time.sleep(5)\n            continue\n        raise","preventionTips":["Pass timeout >= 600 for BFL generations; defaults are tight for heavy jobs.","Limit per-key concurrency so jobs leave the queue quickly.","Use aimage_generation in async stacks to avoid blocking a worker per poll loop."],"tags":["bfl","polling","timeout","sync","image-generation"],"backgroundTag":null,"analyzedSha":"6c2dcb801bf2b75c18f1bb24140e7cf57465cc4d","analyzedAt":"2026-08-15T07:12:03.035Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}