Content filters hitting with no explanation despite being set to annotate only

Graham LaBossiere 0 Reputation points
2026-04-14T22:45:38.1566667+00:00

I'm making requests to GPT 5.2 which are triggering content filtering, of the nature "What does <company> do?".

The response contains is the standard "I'm sorry, but I cannot assist you with that request" and contains:

incomplete_details:
  reason: "content_filter"

However content_filters is set null, so I can't see why. I briefly saw a period yesterday where it was hitting that due to "Protected material for text", which I've since configured to "Annotate only". This doesn't seem like an issue where we're asking a question offensive enough to hit the default filtering checks, but even if it were it's not reporting which filters its hitting, which seems like a bug. What's going on?

Content Safety in Foundry Control Plane
Content Safety in Foundry Control Plane

An Azure service that enables users to identify content that is potentially offensive, risky, or otherwise undesirable. Previously known as Azure Content Moderator.

0 comments No comments

2 answers

Sort by: Most helpful
  1. SAI JAGADEESH KUDIPUDI 3,640 Reputation points Microsoft External Staff Moderator
    2026-04-25T09:18:22.4266667+00:00

    Hi Graham LaBossiere,

    Thank you for the detailed follow-up — you’ve raised very valid points, and I can see why this behavior feels inconsistent at first glance. Let me address your questions directly and suggest the best way to handle this moving forward.

    1. Why do filtered responses return HTTP 200 instead of 4xx?

    This is expected behavior in Azure OpenAI (via Azure AI Foundry).

    Content filtering is part of the model inference pipeline, not a request validation step. That means:

    • HTTP 200 → The request was valid and processed successfully

    If content is filtered → The model returns a safe/refusal response

    HTTP 400 is only returned when the prompt itself is blocked before processing

    In practice, you should rely on response fields such as:

    finish_reason

    The returned message content

    …rather than HTTP status codes to detect filtering.
    2. Why is content_filters sometimes null or missing?

    This can happen and is consistent with current platform behavior.

    Azure OpenAI applies:

    Your configured content filter policy (e.g., “Annotate only”)

    Plus additional built-in safety systems that are always enforced

    When your configured policy triggers, you’ll typically see:

    content_filter_results

    prompt_filter_results

    However, when filtering is triggered by internal safety mechanisms, the service may:

    Return a refusal response

    Not include detailed filter metadata (so content_filters may be null)

    So while it looks like missing data, it doesn’t necessarily indicate a misconfiguration.
    3. Why simple prompts may still get filtered

    Even prompts like “What does <company> do?” can occasionally trigger filtering due to:

    Entity ambiguity or pattern matching

    Context from system prompts or prior messages

    Probabilistic safety classifiers (which can produce false positives)

    The exact trigger isn’t always exposed in the API response.
    Recommended approach

    To handle this reliably in your application:

    • Detect filtering via response fields
      • Check finish_reason == "content_filter"
      • Look for refusal-style responses
    • Treat filtering as a valid outcome
      • Similar to partial or empty responses
    • Log full request/response payloads
      • Helps with troubleshooting and escalation
    • Enable diagnostics
      • Azure Monitor logs (AzureOpenAIRequestLogs) may provide additional insight

    If this HTTP 200 for filtered responses is by design

    • HTTP 200 for filtered responses is by design
    • content_filters is not guaranteed to always be populated
    • Some filtering decisions are not fully exposed today

    Applications should rely on response inspection, not HTTP status codes
    Microsoft Reference Links:

    Hope this helps. If you have any follow-up questions, please let me know. I would be happy to help.
    Please do not forget to "Accept Answer" and "up-vote" wherever the information provided helps you, as this can be beneficial to other community members.

    Was this answer helpful?


  2. Jerald Felix 17,470 Reputation points Volunteer Moderator
    2026-04-15T00:30:06.7133333+00:00

    Hello Graham LaBossiere,

    Greetings! Thanks for raising this question in Q&A forum.

    This is a great observation and you're right to flag it. Here's what's likely happening: Azure OpenAI has two separate layers of content filtering. One is your configurable content filter policy (which you've set to "Annotate only"), and the other is a non-configurable, built-in safety layer that runs independently underneath it. Even simple-looking prompts like "What does <company> do?" can occasionally trip the built-in "Protected material for text" or "Indirect prompt injection" checks depending on how the company name is interpreted internally. The key frustration here — and you've spotted it correctly is that when the block comes from this lower-level system, content_filters comes back as null, giving you no visibility into which filter fired. This does appear to be a transparency gap in the API response.

    Here's what you can do step by step to investigate and work around this:

    Step 1: Double-check your content filter policy is correctly applied

    In Azure AI Foundry (formerly Azure OpenAI Studio), go to Content Filters → confirm your custom policy with "Protected material for text" set to "Annotate only" is actually assigned to your deployment, not just created. A policy that's created but not linked to the deployment won't take effect.

    Step 2: Check the full API response for prompt_filter_results

    Look at the raw API response for the prompt_filter_results field, not just content_filters. Sometimes the block is triggered at the prompt level (input) rather than the completion level (output), and the details appear there instead.

    Step 3: Test with a simplified prompt

    Try sending a very neutral, minimal prompt like "Tell me about Microsoft" to see if the same block occurs. This helps isolate whether the issue is the company name itself or something else in your request payload like the system prompt or conversation history.

    Step 4: Review your system prompt

    If you have a system prompt configured, try temporarily removing it and retesting. Occasionally a system prompt can interact with the built-in filters in unexpected ways, especially if it contains instructions about external entities or company data.

    Step 5: Enable diagnostic logging

    In your Azure OpenAI resource, turn on Diagnostic Settings and send logs to a Log Analytics workspace. The AzureOpenAIRequestLogs table can sometimes surface filter reason details that are not visible in the API response itself.

    Step 6: If the issue persists, raise a support ticket

    If after all the above the content_filters field still returns null with no explanation, this is likely a platform-side bug in filter result reporting. Open an Azure Support request with your resource name, deployment name, a sample prompt that reproduces it, and the full raw API response. The Azure AI team can inspect the filter pipeline on the backend for your specific resource.

    As a quick note: the null response for content_filters when a block occurs is a known transparency limitation in certain edge cases, and Microsoft has been gradually improving this. Your feedback through the support channel will help push that forward.

    If this answer helps you kindly accept the answer which will help others who have similar questions.

    Best Regards,

    Jerald Felix.

    Was this answer helpful?


Your answer

Answers can be marked as 'Accepted' by the question author and 'Recommended' by moderators, which helps users know the answer solved the author's problem.