Genace

fal API error: contained material flagged by a content checker — the 422 content_policy_violation

HTTP 422 content_policy_violation Do not retry as-is

The exact error

The content could not be processed because it contained material flagged by a content checker.

What it means

fal’s error reference lists content_policy_violation as an HTTP 422 returned when an input, such as a text prompt or an uploaded image, is flagged by automated safety systems. The reference marks it as not retryable. It also says the flag can come from fal’s own filter or from one of fal’s partners, and that sensitivity levels vary between partner APIs. The listed categories include NSFW content, illegal acts and hate speech, extreme violence or self-harm, harassment and misinformation, third-party IP infringement, and harmful stereotypes.

So this is not a formatting problem. The request reached the model, and a checker refused the content.

The error body is a list, so one request can produce more than one entry. In openstory issue #1373, a request to an LTX video model came back with two entries, one prefixed body.prompt: and one prefixed body.image_url:. Both the motion prompt and the source still had been flagged.

How to confirm it’s this

fal returns a JSON body with a detail array. Each entry has loc, msg, type and url, and optionally input. fal’s reference tells you to branch on type and not to parse msg. The loc path tells you which field was flagged: ["body", "prompt"] in fal’s own example, and image_url for the image in the openstory report.

In the JS client (@fal-ai/client), any 422 JSON response is thrown as a ValidationError, a subclass of ApiError. If the body has no message field, the error message falls back to the HTTP status text. That is why fal-js issue #145 only showed ValidationError: Unprocessable Entity for a Kling text-to-video call made through fal. The reporter later found the real content_policy_violation entry in fal’s dashboard analytics. A fal maintainer replied that throwing is intended and suggested checking error instanceof ValidationError to get the details. In the client source, the parsed body is on error.body, and error.fieldErrors returns the detail entries.

fal also says some APIs are still moving to this error structure, so an endpoint may not return exactly this shape.

Fix

Read the flagged field before doing anything else:

import { fal, ValidationError } from '@fal-ai/client';

try {
  const result = await fal.subscribe(endpointId, { input });
} catch (error) {
  if (error instanceof ValidationError) {
    for (const e of error.fieldErrors) {
      if (e.type === 'content_policy_violation') {
        // e.loc names the rejected input, e.g. ['body', 'prompt']
        console.error(e.loc.join('.'), e.msg);
      }
    }
  }
  throw error;
}

What to do next depends on the field:

  • The prompt was flagged. The request content has to change so that it complies with fal’s usage policy and the model provider’s policy. Don’t try to reword a prompt so it slips past the checker. The filter enforces policy.
  • An image or other media URL was flagged. Changing the prompt won’t help, because the input media itself was rejected. The openstory team reached the same conclusion: reseeding can’t succeed when the input image is the flagged part.
  • Show the reason to your user. The openstory issue began with a user who lost a whole shot and never learned which input caused it. Pass on the loc value, not a generic “generation failed” message.

Retry or not

No. fal’s reference marks content_policy_violation as not retryable, and the same input gets the same verdict. In openstory #1373, the workflow retried three times with an identical prompt and an identical still, changing only the seed, and all three attempts failed. The fal JS client’s default retry list (429, 502, 503 and 504) doesn’t include 422, so a retry would have to be one you wrote yourself.

If you build agents, treat this error as final for that input. Keep it out of generic retry loops. Return the flagged loc to whoever or whatever can change the input.

When it’s not this

  • no_media_generated. This is also a 422 and also not retryable. It means generation finished but the model produced no output. Its message is The model did not generate the expected output for this prompt.
  • An ordinary validation error. In the JS client, any 422 shows up as ValidationError: Unprocessable Entity. This includes Pydantic type errors that fal passes through, such as string_type, int_parsing and enum, as well as value_error. Check type before you assume moderation. Later in fal-js #145, another user reported the same generic error after adding end_image_url to a Wan 2.2 image-to-video call. The thread never identified the cause.
  • Another provider’s moderation. Direct OpenAI and Google calls use their own wording and their own codes. See the related pages below.

Error text last verified against the sources below on .

Where these facts come from