Skip to main content

Fix Azure OpenAI Structured Output JSON Schema Errors in C#

From StackOverflow .NET 9 Azure.AI.OpenAI 2.1.0 OpenAI 2.1.0
By Rajesh Mishra · Mar 21, 2026 · 9 min read
Verified Mar 2026 .NET 9 Azure.AI.OpenAI 2.1.0
In 30 Seconds

Azure OpenAI structured output 400 errors have three causes: wrong API version (need 2024-08-01-preview or later), unsupported property types (DateTime/Uri/TimeSpan must become string), or using a non-GPT-4o model. Fix by setting the correct API version in AzureOpenAIClientOptions, replacing DateTime with string properties, and verifying your deployment uses GPT-4o 2024-08-06 or later.

⚠️
Error Fix Guide

Root cause analysis and verified fix. Code examples use Azure.AI.OpenAI 2.1.0.

✓ SOLVED

The Error

Your .NET application calls Azure OpenAI with a structured output request and receives one of these 400 responses:

// Error 1: Wrong API version
400 invalid_request_error: "response_format.json_schema is not supported for this API version"

// Error 2: Unsupported type in schema
400 invalid_request_error: "Invalid schema for response_format 'json_schema': ...unsupported type..."

// Error 3: Wrong model
400 invalid_request_error: "Structured outputs are not supported with the current model."

Three distinct errors, three distinct root causes. Each requires a different fix. This guide covers all three with exact C# corrections.

Fixes at a Glance

  1. Wrong API version — set AzureOpenAIClientOptions.ServiceVersion to V2024_08_01_Preview or later
  2. Unsupported property types — replace DateTime, Uri, and TimeSpan properties with string in your schema type
  3. Wrong model — only GPT-4o (2024-08-06+) and GPT-4o-mini support structured outputs; switch deployment or fall back to JSON mode

Root Cause 1: API Version Mismatch

Structured outputs were introduced in the Azure OpenAI REST API at version 2024-08-01-preview. If your AzureOpenAIClient is using an older default API version, any request that includes response_format.json_schema will be rejected immediately — the endpoint does not understand the parameter.

The Azure SDK for .NET defaults to an API version that may not support structured outputs, depending on which SDK release you have installed.

using Azure;
using Azure.AI.OpenAI;

// ❌ Wrong — older API versions don't support structured outputs
var client = new AzureOpenAIClient(
    new Uri(endpoint),
    new AzureKeyCredential(apiKey)); // defaults to older API version

// ✅ Correct — specify a version that supports structured outputs
var options = new AzureOpenAIClientOptions(
    AzureOpenAIClientOptions.ServiceVersion.V2024_08_01_Preview);

var client = new AzureOpenAIClient(
    new Uri(endpoint),
    new AzureKeyCredential(apiKey),
    options);

For new projects, prefer V2024_10_01_Preview or later — it also supports structured outputs and includes additional capability improvements. The V2024_08_01_Preview version is the minimum required.

For the complete list of breaking changes introduced in the Azure.AI.OpenAI 2.x SDK, see the Azure OpenAI SDK v2 Migration Guide for C#.

Root Cause 2: Unsupported .NET Types in the Schema

Azure OpenAI’s strict JSON Schema mode only accepts a subset of JSON Schema types: string, number, boolean, integer, array, object, and null. Several common .NET types do not map to these primitives:

  • DateTime and DateTimeOffset — map to a complex JSON Schema format, not a primitive
  • Uri — serializes as a string but the schema generator may emit type metadata that is rejected
  • TimeSpan — no JSON Schema equivalent

When the Azure OpenAI service receives a schema containing these types, it returns a 400 error indicating the schema is invalid. The error message includes the property name that failed validation.

// ❌ Wrong — DateTime, Uri, TimeSpan are not JSON Schema primitives
public class ArticleSummary
{
    public string Title { get; set; } = string.Empty;
    public DateTime PublishedAt { get; set; }  // ❌ Not supported
    public Uri SourceUrl { get; set; } = null!;  // ❌ Not supported
    public TimeSpan ReadingTime { get; set; }  // ❌ Not supported
}

// ✅ Correct — use string with documentation
public class ArticleSummary
{
    public string Title { get; set; } = string.Empty;

    [Description("ISO 8601 date string, e.g., 2026-03-21")]
    public string PublishedAt { get; set; } = string.Empty;

    [Description("Full URL of the source article")]
    public string SourceUrl { get; set; } = string.Empty;

    [Description("Estimated reading time, e.g., '5 minutes'")]
    public string ReadingTime { get; set; } = string.Empty;
}

The [Description] attribute from System.ComponentModel is included in the generated JSON schema as a description field. The model reads this at inference time and uses it to format its output correctly — it understands “ISO 8601 date string” without needing the type system to enforce it.

After collecting the model’s response, parse the string values back to their .NET types in your application layer using DateTime.Parse, Uri, or TimeSpan.Parse as appropriate.

Root Cause 3: Model Does Not Support Structured Outputs

Structured outputs require a specific model version. Azure OpenAI deployments using older GPT-4 variants, or non-OpenAI models available through Azure AI Foundry, do not support strict JSON schema mode.

ModelStructured OutputsJSON Mode
GPT-4o (2024-08-06+)
GPT-4o-mini
GPT-4 Turbo
DeepSeek-R1
Llama 3.x

If your deployment uses GPT-4 Turbo, DeepSeek-R1, or any Llama variant, you will receive the “Structured outputs are not supported with the current model” error. The fix is one of:

  1. Switch the deployment to GPT-4o with model version 2024-08-06 or later in Azure AI Foundry
  2. Fall back to JSON mode using ChatResponseFormat.CreateJsonObjectFormat() — this asks the model to return valid JSON but does not guarantee schema adherence

JSON mode is the right choice when you cannot change the deployment and the model is capable enough to follow a schema prompt reliably. Structured outputs are preferred for production workloads where downstream code depends on specific field names and types.

Using Structured Outputs Correctly in C#

Once you have the right API version and a compatible model, the SDK call uses ChatResponseFormat.CreateJsonSchemaFormat<T>:

using OpenAI.Chat;

public class ArticleAnalysis
{
    public string Title { get; set; } = string.Empty;
    public string Summary { get; set; } = string.Empty;
    public string[] KeyTopics { get; set; } = [];
    public string Sentiment { get; set; } = string.Empty; // "positive", "neutral", "negative"
}

var chatClient = azureOpenAIClient.GetChatClient("gpt-4o-deployment");

var options = new ChatCompletionOptions
{
    ResponseFormat = ChatResponseFormat.CreateJsonSchemaFormat<ArticleAnalysis>(
        name: "article_analysis",
        strict: true)
};

var completion = await chatClient.CompleteChatAsync(
    [new UserChatMessage($"Analyze this article: {articleText}")],
    options);

var json = completion.Content[0].Text;
var analysis = JsonSerializer.Deserialize<ArticleAnalysis>(json)!;

The name parameter identifies the schema in the API request — use snake_case, no spaces. The strict: true parameter enables guaranteed schema compliance. Without strict: true, the behaviour falls back to best-effort JSON that may not match your schema.

For a full explanation of how ChatResponseFormat.CreateJsonSchemaFormat<T> generates the schema from your C# type, see Azure OpenAI Structured Outputs in C#.

Using Structured Outputs in Semantic Kernel

Semantic Kernel translates ResponseFormat = typeof(T) in OpenAIPromptExecutionSettings to a structured output API call automatically:

using Microsoft.SemanticKernel;
using Microsoft.SemanticKernel.Connectors.OpenAI;

var settings = new OpenAIPromptExecutionSettings
{
    ResponseFormat = typeof(ArticleAnalysis) // SK translates to structured output
};

var result = await kernel.InvokePromptAsync(
    $"Analyze this article: {articleText}",
    new KernelArguments(settings));

var json = result.GetValue<string>()!;
var analysis = JsonSerializer.Deserialize<ArticleAnalysis>(json)!;

The same type restrictions apply when using SK — ArticleAnalysis must not contain DateTime, Uri, or TimeSpan properties. SK does not validate the schema before sending it to Azure OpenAI, so a type with unsupported properties will produce the same 400 error.

Validating Your Schema Locally Before Sending

Before sending your type to Azure OpenAI, generate and inspect the schema it will produce using JsonSchemaExporter from System.Text.Json.Schema (.NET 9+):

using System.Text.Json;
using System.Text.Json.Schema;

// Generate and inspect the schema your type produces
var schema = JsonSchemaExporter.GetJsonSchemaAsNode(
    new JsonSerializerOptions(), typeof(ArticleAnalysis));
Console.WriteLine(schema.ToJsonString(new JsonSerializerOptions { WriteIndented = true }));
// Review for any unsupported types before sending to API

Run this in a test or a small console app when adding a new schema type. Look for any property that produces a $ref, format, or non-primitive type — those are candidates for 400 errors. Fix them before deploying.

Further Reading

⚠ Production Considerations

  • Structured output adds a schema validation step to each response. For very complex or deeply nested schemas (5+ levels of nesting, 50+ properties), this adds 1-3% latency. Consider flattening your response schema if latency is critical.
  • The strict mode schema is generated from your C# type at request time via reflection. If your type has optional nullable properties (string? field), these become 'anyOf: [{type: string}, {type: null}]' in the schema — which is supported. But required reference types that you initialize with defaults (= string.Empty) are still considered required by the schema generator. Test your exact type with JsonSchemaExporter first.

Enjoying this article?

Get weekly .NET + AI insights delivered to your inbox. No spam.

Subscribe Free →

🧠 Architect’s Note

Prefer structured outputs over JSON mode for all production workloads. The reliability guarantee of strict schema compliance eliminates an entire category of parsing errors and null-safety bugs in your downstream code. The API version requirement is a one-time setup cost.

AI-Friendly Summary

Summary

Azure OpenAI structured output 400 errors have three causes: wrong API version (need 2024-08-01-preview or later), unsupported property types (DateTime/Uri/TimeSpan must become string), or using a non-GPT-4o model. Fix by setting the correct API version in AzureOpenAIClientOptions, replacing DateTime with string properties, and verifying your deployment uses GPT-4o 2024-08-06 or later.

Key Takeaways

  • Structured outputs need API version 2024-08-01-preview or later
  • Replace DateTime, DateTimeOffset, Uri, TimeSpan with string in your schema types
  • Only GPT-4o and GPT-4o-mini support structured outputs — not GPT-4 Turbo
  • ChatResponseFormat.CreateJsonSchemaFormat<T>(strict: true) is the correct SDK call
  • Use JsonSchemaExporter.GetJsonSchemaAsNode to validate schemas locally before sending

Implementation Checklist

  • Set AzureOpenAIClientOptions.ServiceVersion to V2024_08_01_Preview or later
  • Replace DateTime/Uri/TimeSpan properties with string in your response type
  • Confirm your deployment uses GPT-4o (2024-08-06 version) or GPT-4o-mini
  • Use ChatResponseFormat.CreateJsonSchemaFormat<T>(strict: true) in ChatCompletionOptions
  • Validate schema locally with JsonSchemaExporter before sending

Frequently Asked Questions

What API version does Azure OpenAI require for structured outputs?

Structured outputs require API version 2024-08-01-preview or later. Earlier API versions return 400 invalid_request_error with 'response_format.json_schema is not supported'. Set the version in AzureOpenAIClientOptions.ServiceVersion.

Why does DateTime cause a 400 error in Azure OpenAI structured outputs?

Azure OpenAI structured outputs only support a subset of JSON Schema types: string, number, boolean, integer, array, object, and null. DateTime, DateTimeOffset, Uri, and TimeSpan are not valid JSON Schema primitive types and cause schema validation errors. Use string with a description like 'ISO 8601 date' instead.

How do I set the Azure OpenAI API version for structured outputs in C#?

Pass AzureOpenAIClientOptions with the correct service version: new AzureOpenAIClientOptions(AzureOpenAIClientOptions.ServiceVersion.V2024_08_01_Preview). Alternatively, use the 2024-10-01-preview or later which also supports structured outputs.

Do all Azure OpenAI models support structured outputs?

No. Only GPT-4o (2024-08-06 or later) and GPT-4o-mini support structured outputs. GPT-4 Turbo, DeepSeek-R1, Llama 3.x, and other non-OpenAI models do not support strict JSON schema mode. These models support JSON mode (response_format: json_object) but not guaranteed schema adherence.

How do I get structured outputs in Semantic Kernel?

Set ResponseFormat = typeof(MyRecord) in OpenAIPromptExecutionSettings. SK translates this to the structured output API call. Ensure your record type only uses JSON Schema-compatible properties (no DateTime, Uri, or complex .NET types without mapping).

What is the difference between JSON mode and structured outputs?

JSON mode (response_format: json_object) asks the model to return valid JSON but does not guarantee schema adherence — fields may be missing or wrong types. Structured outputs (response_format: json_schema with strict: true) guarantee 100% schema compliance. Always prefer structured outputs when available.

How can I validate my schema before sending it to Azure OpenAI?

Use JsonSchemaExporter.GetJsonSchemaAsNode(new JsonSerializerOptions(), typeof(MyRecord)) to generate the JSON schema your type would produce. Inspect it for unsupported types (any .NET type that maps to a complex JSON type) before sending the request.

You Might Also Enjoy

Was this article useful?

Feedback is anonymous and helps us improve content quality.

Discussion

Engineering discussion powered by GitHub Discussions.

#Structured Output #JSON Schema #Error Fix #Azure OpenAI #.NET AI