{"record":{"id":"91dbe7cc56fc21b0","repo":"microsoft/aspire","slug":"aspireradius011","errorCode":"ASPIRERADIUS011","errorMessage":"{provider} cloud-provider credentials are registered per Radius installation (global) and are shared across all environments, but environments {envNames} configure different {provider} credentials that would overwrite one another. Configure a single shared credential for all environments, or deploy them to separate Radius installations. Diagnostic: ASPIRERADIUS011.","messagePattern":"(.+?) cloud-provider credentials are registered per Radius installation \\(global\\) and are shared across all environments, but environments (.+?) configure different (.+?) credentials that would overwrite one another\\. Configure a single shared credential for all environments, or deploy them to separate Radius installations\\. Diagnostic: ASPIRERADIUS011\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/Aspire.Hosting.Radius/Publishing/RadCredentialRegisterStep.cs","lineNumber":214,"sourceCode":"            {\n                aws.Add((env.Name, AwsCredentialIdentity(awsConfig.Credential)));\n            }\n        }\n\n        ThrowIfConflicting(\"Azure\", azure);\n        ThrowIfConflicting(\"AWS\", aws);\n    }\n\n    private static void ThrowIfConflicting(string provider, IReadOnlyList<(string Env, string Identity)> configured)\n    {\n        var distinctIdentities = configured.Select(static c => c.Identity).Distinct(StringComparer.Ordinal).Count();\n        if (distinctIdentities <= 1)\n        {\n            return;\n        }\n\n        var envNames = string.Join(\", \", configured.Select(static c => $\"'{c.Env}'\").Distinct(StringComparer.Ordinal));\n        throw new InvalidOperationException(\n            $\"{provider} cloud-provider credentials are registered per Radius installation (global) and \" +\n            $\"are shared across all environments, but environments {envNames} configure different {provider} \" +\n            \"credentials that would overwrite one another. Configure a single shared credential for all \" +\n            \"environments, or deploy them to separate Radius installations. Diagnostic: ASPIRERADIUS011.\");\n    }\n\n    private static string AzureCredentialIdentity(AzureRadiusCredential credential) => credential switch\n    {\n        AzureRadiusCredential.ServicePrincipal sp => $\"sp|{Canonicalize(sp.TenantId)}|{Canonicalize(sp.ClientId)}\",\n        AzureRadiusCredential.WorkloadIdentity wi => $\"wi|{Canonicalize(wi.TenantId)}|{Canonicalize(wi.ClientId)}\",\n        _ => throw new InvalidOperationException($\"Unknown Azure credential type '{credential.GetType().Name}'.\"),\n    };\n\n    private static string AwsCredentialIdentity(AwsRadiusCredential credential) => credential switch\n    {\n        // The access key id identifies the principal; it is bound via a parameter, so its\n        // resource name is used as a stable proxy without resolving the value here.\n        AwsRadiusCredential.AccessKey ak => $\"access-key|{ak.AccessKeyId.Resource.Name}\",","sourceCodeStart":196,"sourceCodeEnd":232,"githubUrl":"https://github.com/microsoft/aspire/blob/25830f84bd145686607ad00c057b3f84e2e51d43/src/Aspire.Hosting.Radius/Publishing/RadCredentialRegisterStep.cs#L196-L232","documentation":"Radius registers cloud-provider credentials globally per Radius installation, so all environments in one publish share them. When multiple environments configured with the same provider supply different credentials (distinct canonical identities), deploying would silently overwrite one credential with another, so validation refuses up front with diagnostic ASPIRERADIUS011.","triggerScenarios":"Publishing/deploying two or more Aspire environments to the same Radius installation, each configured with a different credential for the same cloud provider (e.g. environment A uses a ServicePrincipal, environment B uses WorkloadIdentity, or two service principals with different tenant/client IDs).","commonSituations":"Teams adding a new environment with its own Azure SP while an existing environment already registers a different credential; copying an environment resource and changing only the client ID; testing prod/staging against a single shared dev Radius control plane.","solutions":["Configure the same credential instance (identical tenant/client or role ARN) for all environments in the publish model.","Deploy the conflicting environments to separate Radius installations (separate control planes) so credentials are registered independently.","Inspect the listed environment names in the message and remove or consolidate the duplicate provider credential registrations."],"exampleFix":"// before\nvar staging = builder.AddAzureEnvironment(\"staging\").WithRadiusCredential(spCredential2);\nvar prod = builder.AddAzureEnvironment(\"prod\").WithRadiusCredential(spCredential1);\n\n// after\nvar sharedCredential = builder.AddAzureRadiusCredential(AzureRadiusCredentialKind.ServicePrincipal, ...);\nvar staging = builder.AddAzureEnvironment(\"staging\").WithRadiusCredential(sharedCredential);\nvar prod = builder.AddAzureEnvironment(\"prod\").WithRadiusCredential(sharedCredential);","handlingStrategy":"validation","validationCode":"// Before publish, collect credentials per provider per environment and assert a single distinct identity\nvar identities = environments\n    .Select(e => GetProviderCredentialIdentity(e, provider))\n    .Distinct()\n    .ToList();\nif (identities.Count > 1)\n    throw new InvalidOperationException($\"Multiple {provider} credentials configured for one Radius installation: {string.Join(\", \", identities)}\");","typeGuard":null,"tryCatchPattern":"try { await publisher.ExecuteAsync(ct); }\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"ASPIRERADIUS011\"))\n{\n    logger.LogError(ex, \"Conflicting provider credentials across environments; consolidate to one credential or separate Radius installations.\");\n}","preventionTips":["Share one credential object across all environments in the same publish model","Use separate Radius installations for environments that genuinely need different credentials","Grep your app host for WithRadiusCredential/AddAzureRadiusCredential calls to audit duplication"],"tags":["radius","azure","aws","credentials","configuration-conflict","publish"],"backgroundTag":"conflicting-config-options","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"}