From c6754fd703cc4d865a436edc3c24d58207387774 Mon Sep 17 00:00:00 2001 From: Mattt Zmuda Date: Fri, 25 Sep 2026 06:38:55 -0700 Subject: [PATCH] Decode the error object in OpenAI Responses results The Responses API returns `error` as an object with a code and a message, or null. OpenAILanguageModel declared it as an array of JSON values, so a response with a non-null error failed to decode as a whole. It now decodes the object, as the Open Responses provider does. --- .../AnyLanguageModel/Models/OpenAILanguageModel.swift | 8 +++++++- Tests/AnyLanguageModelTests/ProviderUsageTests.swift | 10 ++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/Sources/AnyLanguageModel/Models/OpenAILanguageModel.swift b/Sources/AnyLanguageModel/Models/OpenAILanguageModel.swift index a0556fd5..9820d8b8 100644 --- a/Sources/AnyLanguageModel/Models/OpenAILanguageModel.swift +++ b/Sources/AnyLanguageModel/Models/OpenAILanguageModel.swift @@ -1291,7 +1291,7 @@ private enum Responses { let id: String let output: [JSONValue]? let usage: ResponsesUsage? - let error: [JSONValue]? + let error: ResponseError? let outputText: String? let finishReason: String? @@ -1304,6 +1304,12 @@ private enum Responses { case error = "error" } } + + /// The `error` object of a response, which is `null` unless the response failed. + struct ResponseError: Decodable, Sendable { + let code: String? + let message: String? + } } // MARK: - Supporting Types diff --git a/Tests/AnyLanguageModelTests/ProviderUsageTests.swift b/Tests/AnyLanguageModelTests/ProviderUsageTests.swift index 798c74af..c4331da1 100644 --- a/Tests/AnyLanguageModelTests/ProviderUsageTests.swift +++ b/Tests/AnyLanguageModelTests/ProviderUsageTests.swift @@ -859,6 +859,16 @@ import Testing #expect(UsageURLProtocol.recordedBodies.count == 2) } + @Test(arguments: [Provider.responses, .openResponses]) + func responsesDecodeErrorObjects(_ provider: Provider) async throws { + UsageURLProtocol.reset() + var body = provider.response(counts: provider.counts) + body["error"] = ["code": "server_error", "message": "The model failed."] + UsageURLProtocol.enqueue(json: try Self.json(body)) + let response = try await provider.makeSession().respond(to: "Hi") + #expect(response.content == "Hello") + } + @Test(arguments: [Provider.chat, .responses, .openResponses, .gemini]) func toolRoundsAccumulateUsage(_ provider: Provider) async throws { UsageURLProtocol.reset()