预览提示 · 本站为上线前预览:模型清单与费率以正式上线公告为准

TROUBLESHOOTING · ERROR FAQ

Image Generation API Content Filter Errors: Handling & Workarounds

In production, an image API's content filter is not an inconvenience — it is a failure mode your code must handle. Different APIs report the same rejection differently: some as HTTP 4xx status codes, some as a 200 with an error object in the body, some as a queued task that fails later. This guide compares the shapes, lays out a language-agnostic handling pattern around {code, retryable, action}, shows a batch-pipeline design that skips-and-logs instead of dying on item 3, and covers prompt pre-cleaning. Model pages for the two ends of the spectrum: FLUX.2 Pro for text-to-image and Nano Banana Pro for editing.

How APIs report filter rejections: three shapes

  • HTTP 4xx at submit. Cleanest shape: 400/422 with a body naming the filter code. Easy to branch on with a status-code switch.
  • HTTP 200 with error body. Common on async and proxy-style APIs: check the body's code field before treating the response as success — the classic 200-but-error trap.
  • Task fails during polling. Submit succeeds, then the poll returns a terminal FAILURE state with a reason code. Requires handling at the polling stage, not just submit.

The handling pattern: {code, retryable, action}

Normalize every rejection into three fields: what happened (code), whether an identical retry can succeed (retryable), and what to do next (action). Filter rejections are rarely retryable — the fix is a rewrite. Rate limits are retryable — the fix is backoff. Billing and auth errors are neither — the fix is alerting a human. Gate your retry loop on the retryable flag, route non-retryable rejections to a rewrite queue, and log code frequencies: a spike in one filter code is a product signal (a phrasing pattern in your prompts), not just an ops metric.

python
def handle_image_result(resp):
    err = resp.get("error")            # present on filter hits even with HTTP 200
    if not err:
        return resp["url"]             # result URL is the top-level url field
    code, retryable = err["code"], err["retryable"]
    if code.startswith("CONTENT_FILTER"):
        return enqueue_rewrite(resp["prompt"])   # not retryable as-is
    if retryable:
        return retry_with_backoff(resp)
    raise FatalAPIError(code, err["action"])

Batch pipelines: skip and record, don't halt

A 500-image batch will contain a few filter rejections; treat them as expected output, not exceptions. The pattern that survives production: write a per-item record (prompt, code, action) for rejects, continue the batch, then handle rejects in bulk — auto-rewrite the ones whose code suggests phrasing, flag the rest for review. Never wrap the whole batch in a single retry loop: one persistent rejection becomes an infinite loop with a bill attached. On ModAPIS, filter-rejected generations are not charged, so skipping costs nothing but time.

Prompt pre-cleaning that measurably helps

  • Swap film jargon for plain verbs ("shoot" → "photograph").
  • Replace named people with role descriptions.
  • Keep prompts under ~60 words; risk accumulates with length.
  • Strip template boilerplate you don't need this run — every clause is reviewed.
  • For user-generated prompts, maintain a substitution map of your app's common trip-words.

What ModAPIS guarantees at the filter boundary

Every error — filter included — returns the same structure with code, retryable, and action fields, across all models, so one handler covers the catalog. Failed generations are not charged, in any tier. The quickstart has a first request running in five minutes; the model pages for FLUX.2 Pro and Nano Banana Pro list current per-output pricing in credits.

Quick answers

Do all image APIs use HTTP error status codes for filter hits?
No — three shapes exist in the wild: 4xx at submit, 200 with an error body, and async tasks that fail during polling. Handle all three or one of them will eventually be handled by your users instead.
Should I auto-retry a content filter rejection?
No. Filter rejections are deterministic for the same input; retrying the identical prompt just fails again. Route them to a rewrite step, then resubmit once.
Are filter-rejected generations charged?
On ModAPIS, no — failed generations are not charged, including filter rejections. Not every provider works this way, which is worth checking before you architect a skip-and-retry loop.
已复制