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
- Wrong API version — set
AzureOpenAIClientOptions.ServiceVersiontoV2024_08_01_Previewor later - Unsupported property types — replace
DateTime,Uri, andTimeSpanproperties withstringin your schema type - 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:
DateTimeandDateTimeOffset— map to a complex JSON Schema format, not a primitiveUri— serializes as a string but the schema generator may emit type metadata that is rejectedTimeSpan— 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.
| Model | Structured Outputs | JSON 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:
- Switch the deployment to GPT-4o with model version
2024-08-06or later in Azure AI Foundry - 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
- Azure OpenAI structured outputs documentation
- OpenAI.Chat namespace documentation
- System.Text.Json.Schema.JsonSchemaExporter