microsoft/aspire · error · InvalidOperationException
Response missing refresh_token.
Error message
Response missing refresh_token.
What it means
After a successful (2xx) /oauth2/exchange response, AcrLoginService deserializes the body and requires a non-empty refresh_token. If the JSON payload is null or lacks RefreshToken, this InvalidOperationException is thrown.
Solutions
- Verify the POST actually reached Azure Container Registry and not an intercepting proxy (check response content type).
- Re-authenticate with a fresh AAD access token; a stale/invalid token can yield an empty exchange result.
- Retry the exchange; if reproducible, inspect the raw response body and the ACR service health.
Defensive patterns
Strategy: try-catch
Validate before calling
using var doc = response.Headers.ContentType?.MediaType?.Contains("json") == true ? JsonDocument.Parse(await response.Content.ReadAsStringAsync(ct)) : throw new InvalidOperationException("ACR exchange returned non-JSON response; check proxy settings.");
if (!doc.RootElement.TryGetProperty("refresh_token", out var t) || t.GetString() is not { Length: > 0 }) throw new InvalidOperationException("ACR exchange response lacks refresh_token."); Type guard
static bool HasRefreshToken(AcrRefreshTokenResponse? r) => !string.IsNullOrEmpty(r?.RefreshToken);
Try / catch
try { var rt = await ExchangeAadTokenForAcrRefreshTokenAsync(...); } catch (InvalidOperationException ex) when (ex.Message.Contains("refresh_token")) { /* inspect raw response / re-authenticate */ } Prevention
- Verify no proxy rewrites ACR responses (check Content-Type is application/json).
- Use a freshly acquired AAD access token for the exchange.
- Retry once on empty results before failing.
When it happens
Trigger: Calling ExchangeAadTokenForAcrRefreshTokenAsync when the ACR exchange endpoint returns a 2xx body without a refresh_token field (unexpected contract, proxy interference, or empty body).
Common situations: Corporate proxies/gateways returning 200 HTML pages; ACR endpoint behavioral changes; hitting a non-ACR server that accepts the POST but returns a different schema.
Related errors
- POST /oauth2/exchange failed
- Cannot create the cross-scope ACR pull identity
- Existing Azure sandbox group
- A BlobServiceClient could not be configured. Ensure valid…
- A BlobServiceClient could not be configured. Ensure valid…
AI-assisted analysis of microsoft/aspire@25830f84bd (2026-09-16).
Data as JSON: /api/errors/d168521d775316d0.
Report an issue: GitHub.
Appendix: source
Thrown at src/Aspire.Hosting.Azure/AcrLoginService.cs:186
// Read response body as string once
var responseBody = await response.Content.ReadAsStringAsync(cancellationToken).ConfigureAwait(false);
if (!response.IsSuccessStatusCode)
{
var truncatedBody = responseBody.Length <= 1000 ? responseBody : responseBody[..1000] + "…";
throw new HttpRequestException(
$"POST /oauth2/exchange failed {(int)response.StatusCode} {response.ReasonPhrase}. Body: {truncatedBody}",
null,
response.StatusCode);
}
// Deserialize from the string we already read
var tokenResponse = JsonSerializer.Deserialize<AcrRefreshTokenResponse>(responseBody, s_jsonOptions);
if (string.IsNullOrEmpty(tokenResponse?.RefreshToken))
{
throw new InvalidOperationException($"Response missing refresh_token.");
}
return tokenResponse.RefreshToken;
}
}
View on GitHub (pinned to 25830f84bd)