microsoft/aspire · error · InvalidOperationException
Unknown Azure credential type
Error message
Unknown Azure credential type '{credential.GetType().Name}'. What it means
When building a stable identity string for an Azure Radius credential, the code switches over the known AzureRadiusCredential subtypes (ServicePrincipal, WorkloadIdentity). A credential of any other subtype has no defined identity, so this InvalidOperationException is thrown as an internal exhaustiveness guard.
Solutions
- Use only the supported credential kinds: AzureRadiusCredential.ServicePrincipal or AzureRadiusCredential.WorkloadIdentity.
- Align all Aspire.Hosting.Radius and related package versions so the credential type matches what this validator knows.
- If you believe a new credential type should be supported, file an issue with the type name shown in the message.
Example fix
// before var credential = new MyCustomAzureRadiusCredential(tenantId, clientId); env.WithRadiusCredential(credential); // after var credential = new AzureRadiusCredential.ServicePrincipal(tenantId, clientId); env.WithRadiusCredential(credential);
Defensive patterns
Strategy: type-guard
Validate before calling
// Validate the credential kind before registering
bool IsSupportedAzureCredential(AzureRadiusCredential c) =>
c is AzureRadiusCredential.ServicePrincipal or AzureRadiusCredential.WorkloadIdentity;
if (!IsSupportedAzureCredential(credential)) throw new ArgumentException($"Unsupported Azure credential type {credential.GetType().Name}"); Type guard
var ok = credential is AzureRadiusCredential.ServicePrincipal or AzureRadiusCredential.WorkloadIdentity;
Try / catch
try { env.WithRadiusCredential(credential); }
catch (InvalidOperationException ex) when (ex.Message.StartsWith("Unknown Azure credential type"))
{
logger.LogError(ex, "Credential type {Type} is not supported; use ServicePrincipal or WorkloadIdentity.", credential.GetType().Name);
} Prevention
- Only construct credential types exposed by your exact Aspire.Hosting.Radius package version
- Do not subclass AzureRadiusCredential
- Keep all Aspire.* package versions in sync to avoid unknown subtypes
When it happens
Trigger: Passing a custom or newly-added (or incorrectly cast) subclass of AzureRadiusCredential through WithRadiusCredential into credential-conflict validation, where the switch expression finds no matching pattern.
Common situations: Upgrading the Aspire.Hosting.Radius package while referencing an older/newer AzureRadiusCredential type from a mismatched package version; hand-rolling a subclass of AzureRadiusCredential that the validator does not recognize.
Related errors
- Unknown AWS credential type
- ASPIRERADIUS010
- ASPIRERADIUS011
- rad credential register failed with exit code
- A ConfigureRadiusInfrastructure callback changed the value…
AI-assisted analysis of microsoft/aspire@25830f84bd (2026-09-16).
Data as JSON: /api/errors/aeddf74d69ccd3aa.
Report an issue: GitHub.
Appendix: source
Thrown at src/Aspire.Hosting.Radius/Publishing/RadCredentialRegisterStep.cs:225
var distinctIdentities = configured.Select(static c => c.Identity).Distinct(StringComparer.Ordinal).Count();
if (distinctIdentities <= 1)
{
return;
}
var envNames = string.Join(", ", configured.Select(static c => $"'{c.Env}'").Distinct(StringComparer.Ordinal));
throw new InvalidOperationException(
$"{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.");
}
private static string AzureCredentialIdentity(AzureRadiusCredential credential) => credential switch
{
AzureRadiusCredential.ServicePrincipal sp => $"sp|{Canonicalize(sp.TenantId)}|{Canonicalize(sp.ClientId)}",
AzureRadiusCredential.WorkloadIdentity wi => $"wi|{Canonicalize(wi.TenantId)}|{Canonicalize(wi.ClientId)}",
_ => throw new InvalidOperationException($"Unknown Azure credential type '{credential.GetType().Name}'."),
};
private static string AwsCredentialIdentity(AwsRadiusCredential credential) => credential switch
{
// The access key id identifies the principal; it is bound via a parameter, so its
// resource name is used as a stable proxy without resolving the value here.
AwsRadiusCredential.AccessKey ak => $"access-key|{ak.AccessKeyId.Resource.Name}",
AwsRadiusCredential.Irsa irsa => $"irsa|{irsa.IamRoleArn}",
_ => throw new InvalidOperationException($"Unknown AWS credential type '{credential.GetType().Name}'."),
};
// Inputs are validated as GUIDs before reaching here; normalize to the canonical "D"
// form so differing casing/formatting of the same GUID is not treated as a conflict.
private static string Canonicalize(string guid)
=> Guid.TryParse(guid, out var parsed) ? parsed.ToString("D") : guid;
private static async Task<string> ResolveParameterAsync(
IResourceBuilder<ParameterResource> parameter,View on GitHub (pinned to 25830f84bd)