Skip to content

[BUG] Bad status code deserialization in OpenAIError DeserializeOpenAIError #669

@extedosse

Description

@extedosse

Describe the bug

If the OpenAI api returns an error (witnessed via Azure OpenAI Services), with a response like

{
    "requestid": "1b7cfa98-de62-440f-b230-72919bfa42a0",
    "code": 400,
    "message": "Validation error at #/max_completion_tokens: Extra inputs are not permitted"
}

The code flow will try to deserialize the json like this:

internal static OpenAIError DeserializeOpenAIError(JsonElement element, ModelReaderWriterOptions options)
{
    if (element.ValueKind == JsonValueKind.Null)
    {
        return null;
    }
    string code = default;
    string message = default;
    string @param = default;
    string kind = default;
    IDictionary<string, BinaryData> additionalBinaryDataProperties = new ChangeTrackingDictionary<string, BinaryData>();
    foreach (var prop in element.EnumerateObject())
    {
        if (prop.NameEquals("code"u8))
        {
            if (prop.Value.ValueKind == JsonValueKind.Null)
            {
                code = null;
                continue;
            }
            code = prop.Value.GetString();
            continue;
        }
        if (prop.NameEquals("message"u8))
        {
            message = prop.Value.GetString();
            continue;
        }
        if (prop.NameEquals("param"u8))
        {
            if (prop.Value.ValueKind == JsonValueKind.Null)
            {
                @param = null;
                continue;
            }
            @param = prop.Value.GetString();
            continue;
        }
        if (prop.NameEquals("type"u8))
        {
            kind = prop.Value.GetString();
            continue;
        }
        // Plugin customization: remove options.Format != "W" check
        additionalBinaryDataProperties.Add(prop.Name, BinaryData.FromString(prop.Value.GetRawText()));
    }
    return new OpenAIError(code, message, @param, kind, additionalBinaryDataProperties);
}

It tries to read the "code" property and calls GetString() on it, but the response is a number.
throwing the following exception

System.InvalidOperationException
  HResult=0x80131509
  Message=The requested operation requires an element of type 'String', but the target element has type 'Number'.
  Source=System.Text.Json
  StackTrace:
   at System.Text.Json.ThrowHelper.ThrowJsonElementWrongTypeException(JsonTokenType expectedType, JsonTokenType actualType) in System.Text.Json\ThrowHelper.cs:line 288

The behavior is documented here: https://learn.microsoft.com/en-us/dotnet/api/system.text.json.jsonelement.getstring?view=net-9.0
This method does not create a string representation of values other than JSON strings.

I don't know if your api previously returned strings instead of numbers for the code, depending on that you might want to check if the value is a number first and then use GetInt32() on it and call ToString on the number yourselves or simply call ToString() directly.

looking through your repo and searching for "code"u8: this, then you will find a lot of instances of that or very similar code

Steps to reproduce

This does not use OpenAiError directly, but RunError as the type is public, same logic as above applies, see code snippet below for repro.

Code snippets

using System.ClientModel.Primitives;
using System.Text.Json;
using OpenAI;
using OpenAI.Assistants;

namespace ConsoleApp3
{
    internal class Program
    {
        static void Main(string[] args)
        {
            byte[] json = """
                                {
                                    "requestid": "1b7cfa98-de62-440f-b230-72919bfa42a0",
                                    "code": 400,
                                    "message": "Validation error at #/max_completion_tokens: Extra inputs are not permitted"
                                }
                                """u8.ToArray();

#pragma warning disable OPENAI001
            var converter = new JsonModelConverter(new ModelReaderWriterOptions("W"), OpenAIContext.Default);
            var utf8JsonReader = new Utf8JsonReader(json);
            var output = converter.Read(ref utf8JsonReader, typeof(RunError), JsonSerializerOptions.Default);
#pragma warning restore OPENAI001
        }
    }
}

OS

Windows

.NET version

.NET 9

Library version

OpenAI 2.4

Metadata

Metadata

Assignees

Labels

area: externalThis issue is regarding an external experience, such as a companion service or client.issue-addressedWorkflow: The OpenAI maintainers believe the issue to be addressed and ready to close.questionCategory: The issue is seeking information about the library or its usage.

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions