microsoft/aspire · error · InvalidOperationException

Unknown AWS credential type

Error message

Unknown AWS credential type '{credential.GetType().Name}'.

What it means

While computing a stable identity for an AWS Radius credential (AccessKey or Irsa are the known shapes), any other AwsRadiusCredential subtype has no identity rule, so validation throws this InvalidOperationException as an exhaustiveness guard.

Solutions

  1. Use only supported AWS credential kinds: AwsRadiusCredential.AccessKey or AwsRadiusCredential.Irsa.
  2. Align package versions so the credential type comes from the same Aspire.Hosting.Radius version as the validator.
  3. Report the unrecognized type name (from the message) to the Aspire maintainers if it is a shipped type.

Example fix

// before
var credential = new MyCustomAwsRadiusCredential(accessKey, secretKey);
env.WithRadiusCredential(credential);

// after
var credential = new AwsRadiusCredential.AccessKey(accessKeyIdParameter, secretAccessKeyParameter);
env.WithRadiusCredential(credential);
Defensive patterns

Strategy: type-guard

Validate before calling

// Validate the credential kind before registering
bool IsSupportedAwsCredential(AwsRadiusCredential c) =>
    c is AwsRadiusCredential.AccessKey or AwsRadiusCredential.Irsa;
if (!IsSupportedAwsCredential(credential)) throw new ArgumentException($"Unsupported AWS credential type {credential.GetType().Name}");

Type guard

var ok = credential is AwsRadiusCredential.AccessKey or AwsRadiusCredential.Irsa;

Try / catch

try { env.WithRadiusCredential(credential); }
catch (InvalidOperationException ex) when (ex.Message.StartsWith("Unknown AWS credential type"))
{
    logger.LogError(ex, "Credential type {Type} is not supported; use AccessKey or Irsa.", credential.GetType().Name);
}

Prevention

When it happens

Trigger: Supplying a custom or version-mismatched subclass of AwsRadiusCredential to a Radius environment credential registration, then running the credential-conflict validation (ValidateNoConflictingInstallationCredentials).

Common situations: Mixed Aspire.Hosting.Radius package versions across a solution; a hand-written subclass of AwsRadiusCredential; refactoring that accidentally casts the wrong credential object into the AWS slot.

Related errors


AI-assisted analysis of microsoft/aspire@25830f84bd (2026-09-16). Data as JSON: /api/errors/8334a1356d14d582. Report an issue: GitHub.

Appendix: source

Thrown at src/Aspire.Hosting.Radius/Publishing/RadCredentialRegisterStep.cs:234

            $"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,
        CancellationToken cancellationToken)
    {
        return await parameter.Resource.GetValueAsync(cancellationToken).ConfigureAwait(false) ?? string.Empty;
    }

    private static async Task RunRadAsync(
        IReadOnlyList<string> args,
        HashSet<string> secretFlags,
        ILogger logger,

View on GitHub (pinned to 25830f84bd)