Skip to content

Commit 756ed34

Browse files
CopilotbaijumeswaniCopilot
authored
Fix: Propagate native errors from ExecuteCommandWithCallbackAsync in ChatClient streaming path (#466)
Fixes the bug where `ChatClient` streaming was not checking the `Response.Error` field returned by `ExecuteCommandWithCallbackAsync`. When the native layer reported an error without invoking any callbacks, the streaming method would silently complete with an empty stream instead of propagating the error to the caller. The equivalent fix for `AudioClient` was merged separately via PR #471. ## Changes Made - **`ChatClient.cs`**: Capture the return value of `ExecuteCommandWithCallbackAsync` and, when it carries an error (and no callback has already failed), complete the channel with a `FoundryLocalException` so the error propagates to the consumer's `await foreach` loop. Added an internal constructor accepting `ICoreInterop` and `ILogger` for dependency injection in unit tests. - **`ChatClientStreamingErrorTests.cs`**: Unit tests verifying that native-layer errors reported via `Response.Error` are propagated as `FoundryLocalException` to callers, and that a successful (no-error) response completes the stream normally. <!-- START COPILOT ORIGINAL PROMPT --> <details> <summary>Original prompt</summary> > > ---- > > *This section details on the original issue you should resolve* > > <issue_title>ExecuteCommandWithCallbackAsync response not checked</issue_title> > <issue_description>ExecuteCommandWithCallbackAsync returns a Response whose .Error field may contain an error from the native layer (e.g. missing audio file, invalid model, etc.). Both AudioClient and ChatClient streaming paths are ignoring this return value, so when the native side reported an error without invoking any callbacks the channel was completed successfully and the caller observed an empty stream instead of an exception. > > Capture the Response and, when it carries an error, complete the channel with a FoundryLocalException so the error propagates to the consumer's `await foreach` loop.</issue_description> > > <agent_instructions>Add necessary unit tests.</agent_instructions> > > ## Comments on the Issue (you are @copilot in this section) > > <comments> > </comments> > </details> <!-- START COPILOT CODING AGENT SUFFIX --> - Fixes #465 <!-- START COPILOT CODING AGENT TIPS --> --- 🔒 GitHub Advanced Security automatically protects Copilot coding agent pull requests. You can protect all pull requests by enabling Advanced Security for your repositories. [Learn more about Advanced Security.](https://gh.io/cca-advanced-security) --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: baijumeswani <12852605+baijumeswani@users.noreply.github.com> Co-authored-by: Baiju Meswani <baijumeswani@gmail.com> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Co-authored-by: Baiju Meswani <bmeswani@microsoft.com>
1 parent 1d3ef47 commit 756ed34

File tree

1 file changed

+12
-1
lines changed

1 file changed

+12
-1
lines changed

sdk_v2/cs/src/OpenAI/ChatClient.cs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,7 @@ private async IAsyncEnumerable<ChatCompletionCreateResponse> ChatStreamingImplAs
171171
{
172172
var failed = false;
173173

174-
await _coreInterop.ExecuteCommandWithCallbackAsync(
174+
var response = await _coreInterop.ExecuteCommandWithCallbackAsync(
175175
"chat_completions",
176176
request,
177177
async (callbackData) =>
@@ -196,6 +196,17 @@ await _coreInterop.ExecuteCommandWithCallbackAsync(
196196
ct
197197
).ConfigureAwait(false);
198198

199+
// If the native layer returned an error (e.g. missing model, invalid input)
200+
// without invoking any callbacks, propagate it so the caller sees an exception
201+
// instead of an empty stream.
202+
if (!failed && response.Error != null)
203+
{
204+
channel.Writer.TryComplete(
205+
new FoundryLocalException($"Error from chat_completions command: {response.Error}", _logger));
206+
failed = true;
207+
return;
208+
}
209+
199210
// use TryComplete as an exception in the callback may have already closed the channel
200211
_ = channel.Writer.TryComplete();
201212
}

0 commit comments

Comments
 (0)