{"record":{"id":"cfbf639f6f203666","repo":"microsoft/aspire","slug":"azure-sandbox-group-sandboxgroup-name-returned-an-invalid","errorCode":null,"errorMessage":"Azure sandbox group '{sandboxGroup.Name}' returned an invalid resource ID '{resourceId}'.","messagePattern":"Azure sandbox group '(.+?)' returned an invalid resource ID '(.+?)'\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/Aspire.Hosting.Azure.Sandboxes/AzureSandboxContainerDeployment.cs","lineNumber":2332,"sourceCode":"    {\n        if (!resource.Outputs.TryGetValue(name, out var value) || value is null || string.IsNullOrWhiteSpace(value.ToString()))\n        {\n            throw new InvalidOperationException($\"Azure resource '{resource.Name}' is missing required output '{name}'. Ensure Azure infrastructure provisioning completed successfully.\");\n        }\n\n        return value.ToString()!;\n    }\n\n    internal static AzureDevComputeResourceScope CreateDataPlaneScope(AzureSandboxGroupResource sandboxGroup)\n    {\n        ArgumentNullException.ThrowIfNull(sandboxGroup);\n\n        var resourceId = new global::Azure.Core.ResourceIdentifier(GetRequiredOutput(sandboxGroup, \"id\"));\n        if (string.IsNullOrWhiteSpace(resourceId.SubscriptionId) ||\n            string.IsNullOrWhiteSpace(resourceId.ResourceGroupName) ||\n            string.IsNullOrWhiteSpace(resourceId.Name))\n        {\n            throw new InvalidOperationException(\n                $\"Azure sandbox group '{sandboxGroup.Name}' returned an invalid resource ID '{resourceId}'.\");\n        }\n\n        return new AzureDevComputeResourceScope(\n            resourceId.SubscriptionId,\n            resourceId.ResourceGroupName,\n            resourceId.Name,\n            GetRequiredOutput(sandboxGroup, \"location\"));\n    }\n\n    private static string CreateSandboxResourceName(string resourceName, string deployId)\n    {\n        var normalized = new string(resourceName.ToLowerInvariant().Select(static c => char.IsLetterOrDigit(c) ? c : '-').ToArray()).Trim('-');\n        if (string.IsNullOrWhiteSpace(normalized))\n        {\n            normalized = \"app\";\n        }\n","sourceCodeStart":2314,"sourceCodeEnd":2350,"githubUrl":"https://github.com/microsoft/aspire/blob/25830f84bd145686607ad00c057b3f84e2e51d43/src/Aspire.Hosting.Azure.Sandboxes/AzureSandboxContainerDeployment.cs#L2314-L2350","documentation":"Thrown when the 'id' output of an Azure sandbox group parses to an Azure.Core.ResourceIdentifier whose SubscriptionId, ResourceGroupName, or Name component is empty. The library needs those three components to build an AzureDevComputeResourceScope and rejects any malformed resource ID.","triggerScenarios":"CreateDataPlaneScope building `new ResourceIdentifier(GetRequiredOutput(sandboxGroup, \"id\"))` where the id string is not a fully-qualified ARM resource ID (missing subscription, resource group, or name segments).","commonSituations":"A hand-modified or mocked deployment state containing a partial ID like '/subscriptions/.../sandboxGroups' without a name; a custom Bicep template outputting an incomplete ID; typo'd ARM ID format.","solutions":["Verify the sandbox group's 'id' output is a full ARM resource ID: /subscriptions/{sub}/resourceGroups/{rg}/providers/{ns}/{type}/{name}.","Regenerate the deployment state by re-running provisioning so a well-formed ID is emitted.","If using a custom Bicep template, output the resource's `.id` property directly rather than constructing it manually.","Check that resourceId.Name (not the collection-level ID) is being emitted by the template."],"exampleFix":"// before\noutput id string = '/subscriptions/${sub}/sandboxGroups/${name}'\n// after\noutput id string = sandboxGroup.id","handlingStrategy":"validation","validationCode":"static bool IsValidArmId(string id) =>\n    id.StartsWith(\"/subscriptions/\") && id.Split('/').Length >= 9;","typeGuard":"static bool TryParseScope(string id, out (string Sub, string Rg, string Name) scope)\n{\n    var rid = new Azure.Core.ResourceIdentifier(id);\n    scope = (rid.SubscriptionId ?? \"\", rid.ResourceGroupName ?? \"\", rid.Name ?? \"\");\n    return scope.Sub != \"\" && scope.Rg != \"\" && scope.Name != \"\";\n}","tryCatchPattern":null,"preventionTips":["Always emit full ARM resource IDs from Bicep outputs (use resource.id).","Do not construct resource IDs by string concatenation.","Validate deployment-state IDs after every provisioning run in CI."],"tags":["azure","resource-id","sandbox","validation"],"backgroundTag":"invalid-identifier-format","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"}