Skip to content

fix(bfl): read the task status from non-2xx poll responses - #566

Closed
Kamilbenkirane wants to merge 1 commit into
mainfrom
fix/bfl-failed-task-status
Closed

Kamilbenkirane wants to merge 1 commit into
mainfrom
fix/bfl-failed-task-status

Conversation

@Kamilbenkirane

@Kamilbenkirane Kamilbenkirane commented Nov 9, 2026 •

Copy link
Copy Markdown
Member

A failed BFL task can come back from the poll endpoint as a non-2xx response with its status in the JSON body. BFLImagesClient._make_request called _handle_error_response before reading that body, so such a task raised httpx.HTTPStatusError ("bfl API error: {...}"). It should raise the ValueError that names the BFL status, as the loop already does for Error, moderation, No Card Generated (#512) and Task not found. Two BFL pages document this:

  • FLUX 3 image generation: "A failed task can come back as HTTP 503 with a normal JSON body. Read status from the body before treating a 503 as a retryable outage."
  • FLUX Video Edit, on the same polling flow: such requests "fail with HTTP 422, status: "Error", and an explanation in details.error."

The get_result schema in the OpenAPI spec (ResultResponse: id, status, result, progress, details) is the body these responses carry.

Fix:

  • src/celeste/providers/bfl/images/client.py, BFLImagesClient._make_request: the poll loop now parses the JSON body first and checks Ready and the existing terminal statuses. It calls _handle_error_response only after those checks.
    • A non-2xx body with a terminal status raises the existing ValueError, with the status and error/details.
    • Every other non-2xx response still raises httpx.HTTPStatusError as before: a non-JSON outage page, {"detail": ...}, a 429, or an in-progress status.
  • A successful 2xx body that isn't JSON still raises JSONDecodeError. The status list and messages are unchanged.

Overlap: draft #524 renames this file to providers/bfl/flux/client.py and #521 builds on it. git merge-tree shows this change applies to both branches without conflicts.

Validation:

  • make ci passes: Ruff, format, mypy, Bandit, 744 unit tests.

  • Live: test_generate[bfl-flux-2-klein-4b-parameters3] passes on this branch (POST https://api.bfl.ai/v1/flux-2-klein-4b, aspect_ratio 256x1024, polled to Ready).

  • Local, uncommitted, with stubbed poll responses:

    Poll response main This branch
    503 {"status":"Error","details":{...}} HTTPStatusError ValueError: bfl image generation failed (Error): {...}
    422 {"status":"Error",...} HTTPStatusError ValueError
    503 HTML, 429 {"detail":...}, 500 {"status":"Pending"} HTTPStatusError HTTPStatusError (unchanged)
    200 Pending, then Ready returns returns (unchanged)
  • There is no unit test. One would have to stub the transport, and house rules keep that to tests/unit_tests/test_http.py.

  • CHANGELOG is unchanged, following the fix PRs merged since the v1.0.0 tag (fix(bfl): add match_input to the flux-3-image quality choices #548–fix(openai): remove the shut-down gpt-image-1 registration #553).

BFL can return a failed FLUX 3 task as HTTP 503 with a normal JSON body.
The poll loop raised the HTTP error before reading that body, so a failed
task surfaced as an httpx.HTTPStatusError instead of the ValueError that
names its status. The loop now reads the JSON status first and keeps the
HTTP error for responses without a terminal status.
@Kamilbenkirane
Kamilbenkirane deleted the fix/bfl-failed-task-status branch November 9, 2026 11:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant