{"record":{"id":"45e65c5848da12c3","repo":"microsoft/aspire","slug":"adc-request-method-path-returned-an-incomplete-response","errorCode":null,"errorMessage":"ADC request '{method} {path}' returned an incomplete response.","messagePattern":"ADC request '(.+?) (.+?)' returned an incomplete response\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/Aspire.Hosting.Azure.Sandboxes/Internal/Adc/AzureDevComputeClient.cs","lineNumber":278,"sourceCode":"                    // Reconcile by deployment labels rather than retrying the non-idempotent request.\n                    throw new AzureDevComputeCreateException(ex, responseMayHaveBeenLost: (int)response.StatusCode >= 500);\n                }\n                catch (OperationCanceledException ex)\n                {\n                    throw new AzureDevComputeCreateException(ex, responseMayHaveBeenLost: (int)response.StatusCode >= 500);\n                }\n            }\n\n            try\n            {\n                var result = await response.Content.ReadFromJsonAsync<T>(s_jsonSerializerOptions, cancellationToken).ConfigureAwait(false);\n                if (result is null ||\n                    (result is AzureDevComputeDiskImage diskImage && string.IsNullOrWhiteSpace(diskImage.Id)) ||\n                    (result is AzureDevComputeDiskImage { Status: null }) ||\n                    (result is AzureDevComputeDiskImage { Status.State: var state } && string.IsNullOrWhiteSpace(state)) ||\n                    (result is AzureDevComputeSandbox sandbox && string.IsNullOrWhiteSpace(sandbox.Id)))\n                {\n                    throw new InvalidOperationException($\"ADC request '{method} {path}' returned an incomplete response.\");\n                }\n\n                return result;\n            }\n            catch (Exception ex) when (ex is JsonException or InvalidOperationException or HttpRequestException or IOException or NotSupportedException)\n            {\n                // The service may have committed the create before returning an empty or malformed payload.\n                throw new AzureDevComputeCreateException(ex, responseMayHaveBeenLost: true);\n            }\n            catch (OperationCanceledException ex)\n            {\n                throw new AzureDevComputeCreateException(ex, responseMayHaveBeenLost: true);\n            }\n        }\n    }\n\n    private async Task<HttpResponseMessage> SendWithRetryAsync(\n        AzureDevComputeResourceScope scope,","sourceCodeStart":260,"sourceCodeEnd":296,"githubUrl":"https://github.com/microsoft/aspire/blob/25830f84bd145686607ad00c057b3f84e2e51d43/src/Aspire.Hosting.Azure.Sandboxes/Internal/Adc/AzureDevComputeClient.cs#L260-L296","documentation":"AzureDevComputeClient validates that a deserialized ADC (Azure Dev Compute) create-response contains the required fields: the result must be non-null, and disk images must have a non-empty Id and Status.State while sandboxes must have a non-empty Id. If any of these invariants are missing from an otherwise successful response, the client treats the response as unusable and throws InvalidOperationException naming the HTTP method and path.","triggerScenarios":"Calling the ADC API via SendCreateAsync when the service returns HTTP success (2xx) but the deserialized body is null, a AzureDevComputeDiskImage without Id or Status/Status.State, or a AzureDevComputeSandbox without an Id.","commonSituations":"ADC service bugs or API version drift returning partial payloads; proxies/gateways stripping response fields; a mismatch between the client's DTO shape and the actual service contract; the sandbox/disk image being deleted or not yet initialized between creation and the response.","solutions":["Log the raw response body for the failing '{method} {path}' request and compare it with the AzureDevComputeDiskImage/AzureDevComputeSandbox DTOs to find the missing field.","Update to the latest Aspire.Hosting.Azure.Sandboxes package where the DTOs match the current ADC API contract.","Check the ADC API version/endpoint being used; pin to an API version known to return complete payloads.","If triggered by propagation delay, poll the resource (GET) until Id/Status.State are populated instead of relying on the create response.","Inspect any proxy, gateway, or custom HttpClient handler in the pipeline that could alter or truncate response JSON."],"exampleFix":"// before: assuming create response is complete\nvar sandbox = await client.SendCreateAsync(request, ct);\nUse(sandbox.Id);\n// after: tolerate incomplete create response by fetching the resource\nvar sandbox = await client.SendCreateAsync(request, ct);\nsandbox ??= await client.GetAsync(name, ct);\nif (string.IsNullOrWhiteSpace(sandbox?.Id)) { throw ... }","handlingStrategy":"try-catch","validationCode":"// Pre-flight: probe the ADC resource before relying on the create response\nvar sandbox = await client.GetAsync(name, ct);\nif (sandbox is null || string.IsNullOrWhiteSpace(sandbox.Id))\n{\n    throw new InvalidOperationException(\"ADC sandbox not yet available; poll until Id/Status.State are populated.\");\n}","typeGuard":"static bool IsComplete(AzureDevComputeResult? r) => r switch\n{\n    null => false,\n    AzureDevComputeDiskImage d => !string.IsNullOrWhiteSpace(d.Id) && d.Status?.State is { Length: > 0 },\n    AzureDevComputeSandbox s => !string.IsNullOrWhiteSpace(s.Id),\n    _ => false\n};","tryCatchPattern":"try\n{\n    var result = await client.SendCreateAsync(request, ct);\n    if (!IsComplete(result)) { /* retry with GET */ }\n}\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"returned an incomplete response\"))\n{\n    // log method/path from message, poll the resource, then retry\n}","preventionTips":["After a create call, always verify Id/Status.State before use and fall back to a GET poll.","Pin a known-good ADC API version and keep the client package up to date.","Log raw response bodies for ADC calls to catch contract drift early.","Treat successful-but-partial ADC responses as retryable rather than fatal."],"tags":["azure","http-response","deserialization","sandboxes"],"backgroundTag":"unexpected-response-shape","analyzedSha":"25830f84bd145686607ad00c057b3f84e2e51d43","analyzedAt":"2026-09-16T11:10:06.193Z","contentChangedAt":"2026-09-16T11:10:06.193Z","schemaVersion":2},"datasetVersion":"2026-09-21T04:17:39.646Z"}