diff --git a/src/Libraries/Microsoft.Extensions.AI.Abstractions/Contents/ErrorContent.cs b/src/Libraries/Microsoft.Extensions.AI.Abstractions/Contents/ErrorContent.cs
index ceca3002f88..4588531262b 100644
--- a/src/Libraries/Microsoft.Extensions.AI.Abstractions/Contents/ErrorContent.cs
+++ b/src/Libraries/Microsoft.Extensions.AI.Abstractions/Contents/ErrorContent.cs
@@ -2,8 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.
using System.Diagnostics;
-using System.Text.Json.Serialization;
-using Microsoft.Shared.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
namespace Microsoft.Extensions.AI;
@@ -16,33 +15,33 @@ namespace Microsoft.Extensions.AI;
public class ErrorContent : AIContent
{
/// The error message.
- private string _message;
+ private string? _message;
- /// Initializes a new instance of the class with the specified message.
- /// The message to store in this content.
- [JsonConstructor]
- public ErrorContent(string message)
+ /// Initializes a new instance of the class with the specified error message.
+ /// The error message to store in this content.
+ public ErrorContent(string? message)
{
- _message = Throw.IfNull(message);
+ _message = message;
}
/// Gets or sets the error message.
+ [AllowNull]
public string Message
{
- get => _message;
- set => _message = Throw.IfNull(value);
+ get => _message ?? string.Empty;
+ set => _message = value;
}
- /// Gets or sets the error code.
+ /// Gets or sets an error code associated with the error.
public string? ErrorCode { get; set; }
- /// Gets or sets the error details.
+ /// Gets or sets additional details about the error.
public string? Details { get; set; }
/// Gets a string representing this instance to display in the debugger.
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private string DebuggerDisplay =>
- $"Error = {Message}" +
- (ErrorCode is not null ? $" ({ErrorCode})" : string.Empty) +
- (Details is not null ? $" - {Details}" : string.Empty);
+ $"Error = \"{Message}\"" +
+ (!string.IsNullOrWhiteSpace(ErrorCode) ? $" ({ErrorCode})" : string.Empty) +
+ (!string.IsNullOrWhiteSpace(Details) ? $" - \"{Details}\"" : string.Empty);
}
diff --git a/src/Libraries/Microsoft.Extensions.AI.OpenAI/OpenAIResponseChatClient.cs b/src/Libraries/Microsoft.Extensions.AI.OpenAI/OpenAIResponseChatClient.cs
index 566aac8fa63..70768f07caa 100644
--- a/src/Libraries/Microsoft.Extensions.AI.OpenAI/OpenAIResponseChatClient.cs
+++ b/src/Libraries/Microsoft.Extensions.AI.OpenAI/OpenAIResponseChatClient.cs
@@ -132,6 +132,11 @@ public async Task GetResponseAsync(
break;
}
}
+
+ if (openAIResponse.Error is { } error)
+ {
+ message.Contents.Add(new ErrorContent(error.Message) { ErrorCode = error.Code });
+ }
}
return response;
@@ -246,6 +251,24 @@ public async IAsyncEnumerable GetStreamingResponseAsync(
break;
}
+
+ case StreamingResponseErrorUpdate errorUpdate:
+ yield return new ChatResponseUpdate
+ {
+ CreatedAt = createdAt,
+ MessageId = lastMessageId,
+ ModelId = modelId,
+ ResponseId = responseId,
+ Contents =
+ [
+ new ErrorContent(errorUpdate.Message)
+ {
+ ErrorCode = errorUpdate.Code,
+ Details = errorUpdate.Param,
+ }
+ ],
+ };
+ break;
}
}
}
diff --git a/test/Libraries/Microsoft.Extensions.AI.Abstractions.Tests/Contents/ErrorContentTests.cs b/test/Libraries/Microsoft.Extensions.AI.Abstractions.Tests/Contents/ErrorContentTests.cs
index 2564f6bc2c9..8744636b6ec 100644
--- a/test/Libraries/Microsoft.Extensions.AI.Abstractions.Tests/Contents/ErrorContentTests.cs
+++ b/test/Libraries/Microsoft.Extensions.AI.Abstractions.Tests/Contents/ErrorContentTests.cs
@@ -8,6 +8,19 @@ namespace Microsoft.Extensions.AI;
public class ErrorContentTests
{
+ [Fact]
+ public void Constructor_NormalizesNullToEmpty()
+ {
+ ErrorContent content = new(null!);
+ Assert.Empty(content.Message);
+
+ content.Message = "test";
+ Assert.Equal("test", content.Message);
+
+ content.Message = null!;
+ Assert.Empty(content.Message);
+ }
+
[Fact]
public void Constructor_ShouldInitializeProperties()
{