microsoft/semantic-kernel · error · KernelException
Unexpected response from {url}
Error message
Unexpected response from {url} What it means
The OpenAIFileService sends an HTTP GET to the files endpoint. After SendWithSuccessCheckAsync passes (HTTP 2xx), the response body is deserialized to TModel. If deserialization yields null (empty body or JSON 'null'), KernelException is thrown with the raw body preserved in the exception's Data dictionary under 'ResponseData'. This is distinct from an HTTP error — the request succeeded but the body was unusable.
Source
Thrown at dotnet/src/Connectors/Connectors.OpenAI/Services/OpenAIFileService.cs:218
{
using var request = HttpRequest.CreateDeleteRequest(this.PrepareUrl(url));
this.AddRequestHeaders(request);
using var _ = await this._httpClient.SendWithSuccessCheckAsync(request, cancellationToken).ConfigureAwait(false);
}
private async Task<TModel> ExecuteGetRequestAsync<TModel>(string url, CancellationToken cancellationToken)
{
using var request = HttpRequest.CreateGetRequest(this.PrepareUrl(url));
this.AddRequestHeaders(request);
using var response = await this._httpClient.SendWithSuccessCheckAsync(request, cancellationToken).ConfigureAwait(false);
var body = await response.Content.ReadAsStringWithExceptionMappingAsync(cancellationToken).ConfigureAwait(false);
var model = JsonSerializer.Deserialize<TModel>(body);
return
model ??
throw new KernelException($"Unexpected response from {url}")
{
Data = { { "ResponseData", body } },
};
}
private async Task<(Stream Stream, string? MimeType)> StreamGetRequestAsync(string url, CancellationToken cancellationToken)
{
using var request = HttpRequest.CreateGetRequest(this.PrepareUrl(url));
this.AddRequestHeaders(request);
var response = await this._httpClient.SendWithSuccessCheckAsync(request, cancellationToken).ConfigureAwait(false);
try
{
return
(new HttpResponseStream(
await response.Content.ReadAsStreamAndTranslateExceptionAsync(cancellationToken).ConfigureAwait(false),
response),
response.Content.Headers.ContentType?.MediaType);
}View on GitHub (pinned to c028a0c7dc)
Solutions
- Verify the endpoint base URL and (for Azure) the api-version query parameter are correct for the files API.
- Inspect the exception's Data['ResponseData'] to see the raw body — this reveals whether it's empty, HTML, or malformed JSON.
- Confirm the API key and organization headers are valid; some proxies return 200 with an error body.
- Check that the file ID or resource path actually exists on the target deployment.
Example fix
// before — wrong base URL or stale api-version
var fileService = new OpenAIFileService("https://my-resource.openai.azure.com/", apiKey, apiVersion: "2023-05-15");
// after — correct files endpoint and current api-version
var fileService = new OpenAIFileService("https://my-resource.openai.azure.com/openai/files", apiKey, apiVersion: "2024-05-01"); Defensive patterns
Strategy: retry
Validate before calling
// Pre-call: verify the endpoint and api-version are configured
if (string.IsNullOrWhiteSpace(endpointUrl))
throw new InvalidOperationException("File service endpoint URL is required.");
if (isAzure && string.IsNullOrWhiteSpace(apiVersion))
throw new InvalidOperationException("Azure OpenAI requires an api-version."); Try / catch
try
{
var file = await fileService.GetFileAsync(fileId, ct);
}
catch (KernelException ex) when (ex.Message.Contains("Unexpected response"))
{
var rawBody = ex.Data.Contains("ResponseData") ? ex.Data["ResponseData"]?.ToString() : "<none>";
logger.LogError("File GET returned unparseable body: {Body}", rawBody);
throw;
} Prevention
- Always inspect ex.Data['ResponseData'] — it contains the raw body that failed to deserialize.
- Pin the Azure api-version to one tested with your connector version.
- Use integration tests against the real endpoint to catch envelope-shape changes early.
When it happens
Trigger: Calling a file-service GET operation (e.g. GetFileAsync, list files) where the server returns 200 with an empty body, a JSON literal 'null', or a body whose shape doesn't match TModel and deserializes to null.
Common situations: Azure OpenAI api-version mismatch causing a different response envelope. A reverse proxy returning a 200 status page (HTML) for a route that doesn't exist. Pointing the file service at a base URL for a different API tier that returns empty responses. The file ID not existing on a server that returns 200+null instead of 404.
Related errors
- Response is not available.
- Expected {data.Count} text embedding(s), but received {embed
- Failed to parse response: {responseText}
- Configuration section '{section}' not found
- Failed to get a response from the chat completion service.
AI-assisted analysis of microsoft/semantic-kernel@c028a0c7dc (2026-08-13).
Data as JSON: /api/errors/3fccedfe914e2324.
Report an issue: GitHub.