FLUX moderation reasons: handling the block vs a Sume job error
How to code the handler: BFL returns a Moderation Reasons array in details. A failed Sume job returns an error category and next action, not a reasons array.

When BFL polling returns Request Moderated or Content Moderated, result is null and details["Moderation Reasons"] lists categories such as Violence. A Sume job that cannot generate ends as failed with public error metadata (category, stage, retryability, public reason, next action); the docs list no reasons array.
BFL facts are from its errors page and release notes (read 2026-10-01); Sume facts from Errors and credits. For the stage split itself, see Request Moderated vs Content Moderated.
What does a failed Sume job expose?
The docs say failed jobs expose public error metadata such as category, stage, retryability, retry-after seconds, public reason, and next action, and that internal provider payloads are not public API fields. So a client cannot branch on a provider's moderation category list; it branches on the job category.
| Category | Typical next action in the docs |
|---|---|
validation | Fix input. |
generation_rejected | Inspect events and fix unsupported input. |
generation_unavailable | Retry later. |
quota | Add funds or lower request cost. |
How should the handler differ?
Against BFL, switch on status and read the reasons array to build a user message. Against Sume, read the job's category and next action. A generation_rejected job points you at the job events and at unsupported input, and the docs give no list of policy categories to show a user. Do not retry it unchanged, because the stated action is to change the input.
Separate this from input that Sume could not fetch. image_not_fetchable and input_media_unreachable mean Sume could not fetch or mirror media safely; the fix is a public HTTPS image URL, not a different prompt.
What does a router look like?
A small router makes the split explicit. This sketch switches on the BFL status and on a Sume job category; field names for the Sume side follow the docs' wording, so confirm them against a real failed job.
function userMessage(kind, body) {
if (kind === "bfl") {
const reasons = (body.details || {})["Moderation Reasons"] || [];
if (body.status === "Request Moderated") return "Input blocked: " + reasons.join(", ");
if (body.status === "Content Moderated") return "Output blocked: " + reasons.join(", ");
return null;
}
if (body.status !== "failed") return null;
const cat = body.error && body.error.category;
if (cat === "generation_rejected") return "Not generated. Change the input.";
if (cat === "validation") return "Fix the request fields.";
return "Could not generate. Retry later.";
}What can I tell a user?
Keep it to what you know: the request was not generated, and which category came back. Include the Sume request id if they contact support, and leave out API keys and signed URLs, as the docs advise. This post does not describe Sume's policy rules; those are not in the sources cited.
Sources
Related posts
More in Developers
- FLUX API polling_url and regional hosts vs Sume job polling
BFL says to poll the polling_url it returns on api.bfl.ai and its EU and US hosts. Sume has no region choice: you poll the status URL in the job envelope.
- Upload 30 reference images to a Sume Format run (images only)
A Format run takes up to 30 images in attachments[], type input_image, by public HTTPS URL or asset_id. Video and audio attachments are not supported today.
- Gemini 2.5 access limited, not deprecated: what new projects do
Gemini 2.5 access is limited to past users but not deprecated. Read the model list at runtime instead of hard-coding ids; Sume exposes /v1/catalog for that.
- Gemini 2.5 not available in a new project: what to do
Google's September 18 changelog limits Gemini 2.5 models to users who already used them. New projects are pointed to 3.5 Flash-Lite or 3.8 Flash.
Written by Sume