{"record":{"id":"00b91a1c0f76ab04","repo":"microsoft/aspire","slug":"app-service-plan-id-appserviceplanid-does-not-contain-a","errorCode":null,"errorMessage":"App Service plan id '{appServicePlanId}' does not contain a subscription id.","messagePattern":"App Service plan id '(.+?)' does not contain a subscription id\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/Aspire.Hosting.Azure.AppService/AppSvcUrls.cs","lineNumber":34,"sourceCode":"    internal static async Task<MarkdownString> GetPortalLinkAsync(AzureAppServiceEnvironmentResource computerEnv, string siteName, string? deploymentSlot, CancellationToken cancellationToken)\n    {\n        var planIdValue = await computerEnv.PlanIdOutputReference.GetValueAsync(cancellationToken).ConfigureAwait(false)\n            ?? throw new InvalidOperationException($\"Missing app service plan id output for '{computerEnv.Name}'.\");\n        var (subscriptionId, resourceGroupName) = GetSubscriptionAndResourceGroup(planIdValue);\n        var resourceId = $\"{AzurePortalUrls.GetResourceGroupResourceId(subscriptionId, resourceGroupName)}{SiteResourceType}{siteName}\";\n\n        if (!string.IsNullOrWhiteSpace(deploymentSlot))\n        {\n            resourceId += $\"{SlotPathPrefix}{deploymentSlot}\";\n        }\n\n        return AzurePortalUrls.GetResourceLink(resourceId);\n    }\n\n    private static (string SubscriptionId, string ResourceGroupName) GetSubscriptionAndResourceGroup(string appServicePlanId)\n    {\n        var planId = new ResourceIdentifier(appServicePlanId);\n        var subscriptionId = planId.SubscriptionId ?? throw new InvalidOperationException($\"App Service plan id '{appServicePlanId}' does not contain a subscription id.\");\n        var resourceGroupName = planId.ResourceGroupName ?? throw new InvalidOperationException($\"App Service plan id '{appServicePlanId}' does not contain a resource group name.\");\n\n        return (subscriptionId, resourceGroupName);\n    }\n}\n","sourceCodeStart":16,"sourceCodeEnd":40,"githubUrl":"https://github.com/microsoft/aspire/blob/25830f84bd145686607ad00c057b3f84e2e51d43/src/Aspire.Hosting.Azure.AppService/AppSvcUrls.cs#L16-L40","documentation":"GetSubscriptionAndResourceGroup parses the App Service plan ID with Azure ResourceIdentifier; a subscription id is required to build the portal resource-group URL. Missing it throws this InvalidOperationException.","triggerScenarios":"PlanIdOutputReference value is not a fully-qualified ARM resource ID (no /subscriptions/<id>/ segment) — e.g. a partial ID or placeholder from a custom module.","commonSituations":"Stubbed plan IDs in tests; custom Bicep outputs returning names instead of full IDs; upstream deployment misconfiguration.","solutions":["Ensure the plan ID is a full ARM ID: /subscriptions/<sub>/resourceGroups/<rg>/providers/Microsoft.Web/serverfarms/<plan>","Return the plan resource's .id property from the Bicep output rather than a name","Validate the ID with ResourceIdentifier before parsing","Fix the emitting module/deployment output"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"if (Azure.ResourceManager.ResourceIdentifier.TryParse(planId, out var rid) && rid.SubscriptionId is not null)\n{\n    // safe to parse\n}","typeGuard":"bool HasSubscription(string? id) => id is not null && id.Contains(\"/subscriptions/\");","tryCatchPattern":"try { var link = await AppSvcUrls.GetPortalLinkAsync(env, site, slot, ct); }\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"does not contain a subscription id\")) { /* log malformed plan id */ }","preventionTips":["Return serverfarms .id from Bicep outputs, not names","Validate ARM IDs with ResourceIdentifier before parsing","Avoid placeholder plan IDs in test/stub environments"],"tags":["azure","arm","resource-id","app-service"],"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"}