microsoft/aspire · error · InvalidOperationException
ADC request ' ' failed with HTTP ( ).
Error message
ADC request '{method} {path}' failed with HTTP {(int)response.StatusCode} ({response.ReasonPhrase}). {message}{permissionHint} What it means
EnsureSuccessAsync is the ADC client's non-success HTTP handler: for any non-success status it reads an error message from the response body and throws InvalidOperationException including the method, path, numeric status code, reason phrase, body message, and — for 403 — a hint to verify the caller has the Container Apps SandboxGroup Data Owner role on the sandbox group. It is raised by every SendAsync/SendCreateAsync call that gets an error status.
Solutions
- If status is 403, assign the Container Apps SandboxGroup Data Owner role to the calling principal on the sandbox group and wait a few minutes for propagation, then retry.
- Read the embedded message from the exception to identify the specific status (401 vs 404 vs 429 vs 5xx) and address accordingly.
- Verify your Azure credentials (az login, managed identity, or service principal) target the correct tenant and subscription.
- Retry transient failures (429/5xx) with backoff; check Azure status for ADC outages.
- Confirm the sandbox group name/path used in the request is correct.
Example fix
// before: no RBAC role on principal // HTTP 403 thrown by EnsureSuccessAsync // after (Azure CLI) az role assignment create --assignee <principalId> --role "Container Apps SandboxGroup Data Owner" --scope <sandboxGroupId>
Defensive patterns
Strategy: retry
Validate before calling
// Pre-flight: verify the principal's RBAC role before calling ADC az role assignment list --assignee <principalId> --scope <sandboxGroupId> // Expect "Container Apps SandboxGroup Data Owner" in results
Try / catch
try
{
await client.SendAsync(request, ct);
}
catch (InvalidOperationException ex) when (ex.Message.Contains("HTTP 403"))
{
// grant SandboxGroup Data Owner role, wait for propagation, retry with backoff
}
catch (InvalidOperationException ex) when (ex.Message.Contains("HTTP 429") || ex.Message.Contains("HTTP 5"))
{
// transient: retry with exponential backoff
} Prevention
- Assign Container Apps SandboxGroup Data Owner to your principal before first use; allow propagation time.
- Include a short startup retry with backoff for 403/429/5xx on ADC calls.
- Verify credentials (tenant/subscription) before running AppHosts that use ADC.
- Surface the exception's embedded status code and message in your diagnostics.
When it happens
Trigger: Any ADC HTTP request (via SendAsync or SendCreateAsync) that returns 4xx/5xx; most specifically an HTTP 403 Forbidden when the calling principal lacks the Container Apps SandboxGroup Data Owner role assignment.
Common situations: RBAC role assignment not yet propagated right after granting access (the hint notes propagation delay); wrong tenant/subscription; expired or insufficient credentials; sandbox group not found (404); service outage (5xx).
Understand the failure class
Background: "API error: {status}" and "HTTP 401/403/404/429/5xx" errors: non-2xx HTTP responses explained — this error's family across 27 libraries.
Related errors
- ADC request ' ' returned an empty response.
- az aks get-credentials failed
- POST /oauth2/exchange failed
- 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/3c1cc64e19799961.
Report an issue: GitHub.
Appendix: source
Thrown at src/Aspire.Hosting.Azure.Sandboxes/Internal/Adc/AzureDevComputeClient.cs:465
return _accessToken.Token;
}
_accessToken = await credential.GetTokenAsync(new TokenRequestContext(s_authorizationScopes), cancellationToken).ConfigureAwait(false);
return _accessToken.Token;
}
private static async Task EnsureSuccessAsync(HttpResponseMessage response, HttpMethod method, string path, CancellationToken cancellationToken)
{
if (response.IsSuccessStatusCode)
{
return;
}
var message = await GetErrorMessageAsync(response, cancellationToken).ConfigureAwait(false);
var permissionHint = response.StatusCode == HttpStatusCode.Forbidden
? " Verify that the calling principal has the Container Apps SandboxGroup Data Owner role on the sandbox group; newly-created role assignments can take a short time to propagate."
: string.Empty;
throw new InvalidOperationException($"ADC request '{method} {path}' failed with HTTP {(int)response.StatusCode} ({response.ReasonPhrase}). {message}{permissionHint}");
}
private static Task<string> GetErrorMessageAsync(HttpResponseMessage response, CancellationToken cancellationToken)
{
cancellationToken.ThrowIfCancellationRequested();
if (response.Content.Headers.ContentLength == 0)
{
return Task.FromResult(string.Empty);
}
return Task.FromResult("The service returned an error response whose details were redacted.");
}
private static string GetSandboxGroupPath(AzureDevComputeResourceScope scope)
{
return $"subscriptions/{Escape(scope.SubscriptionId)}/resourceGroups/{Escape(scope.ResourceGroupName)}/sandboxGroups/{Escape(scope.SandboxGroupName)}";
}
View on GitHub (pinned to 25830f84bd)