microsoft/aspire · error · InvalidOperationException
Unexpected icon variant
Error message
Unexpected icon variant: {iconVariant} What it means
MapIconVariant converts ApplicationModel.IconVariant (Regular, Filled, or null) to the dashboard proto IconVariant. Null defaults to Regular, but any non-null unknown value has no representation and throws. This guards enum exhaustiveness when converting app-model data to the dashboard view model.
Solutions
- Only assign IconVariant.Regular or IconVariant.Filled when annotating resources
- Use Enum.IsDefined to validate values read from external data before mapping
- Align Aspire.Hosting and dashboard package versions so enums match
- Catch InvalidOperationException and fall back to the default (Regular) variant
Example fix
// before var variant = (IconVariant)storedValue; // after var variant = Enum.IsDefined(typeof(IconVariant), storedValue) ? (IconVariant)storedValue : IconVariant.Regular;
Defensive patterns
Strategy: try-catch
Validate before calling
if (iconVariant is not (IconVariant.Regular or IconVariant.Filled or null))
{
iconVariant = IconVariant.Regular;
} Type guard
bool IsKnownIconVariant(IconVariant? v) => v is null or IconVariant.Regular or IconVariant.Filled;
Try / catch
try
{
protoVariant = MapIconVariant(iconVariant);
}
catch (InvalidOperationException ex) when (ex.Message.StartsWith("Unexpected icon variant"))
{
protoVariant = IconVariant.Regular; // default variant
} Prevention
- Set icon variants only through typed APIs, not casts
- Validate enum values read from persisted/external data
- Keep Aspire.ApplicationModel and dashboard packages on the same version
- Treat unknown variants as Regular at ingestion time
When it happens
Trigger: FromSnapshot/ToViewModel encountering an IconVariant value other than Regular, Filled, or null — e.g. an out-of-range cast, a new enum member from a different Aspire version, or manually constructed resource metadata.
Common situations: Custom resource publishers setting icon variants via unchecked casts; mixed Aspire package versions where the enum gained a member; deserialized model data carrying invalid values.
Understand the failure class
Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.
Related errors
- Unexpected dashboard persistence mode
- Unexpected input type
- Unexpected MillisecondsDisplay value
- AppHost:ResourceService:ApiKey is not specified in…
- ArgumentOutOfRangeException: Specified argument was out of…
AI-assisted analysis of microsoft/aspire@25830f84bd (2026-09-16).
Data as JSON: /api/errors/533f8811e5a82d8a.
Report an issue: GitHub.
Appendix: source
Thrown at src/Aspire.Hosting/Dashboard/proto/Partials.cs:166
{
return healthStatus switch
{
Microsoft.Extensions.Diagnostics.HealthChecks.HealthStatus.Healthy => HealthStatus.Healthy,
Microsoft.Extensions.Diagnostics.HealthChecks.HealthStatus.Degraded => HealthStatus.Degraded,
Microsoft.Extensions.Diagnostics.HealthChecks.HealthStatus.Unhealthy => HealthStatus.Unhealthy,
_ => throw new InvalidOperationException("Unknown health status: " + healthStatus),
};
}
}
private static IconVariant MapIconVariant(Hosting.ApplicationModel.IconVariant? iconVariant)
{
return iconVariant switch
{
Hosting.ApplicationModel.IconVariant.Regular => IconVariant.Regular,
Hosting.ApplicationModel.IconVariant.Filled => IconVariant.Filled,
null => IconVariant.Regular,
_ => throw new InvalidOperationException("Unexpected icon variant: " + iconVariant)
};
}
private static ResourceCommandState MapCommandState(Hosting.ApplicationModel.ResourceCommandState state)
{
return state switch
{
Hosting.ApplicationModel.ResourceCommandState.Enabled => ResourceCommandState.Enabled,
Hosting.ApplicationModel.ResourceCommandState.Disabled => ResourceCommandState.Disabled,
Hosting.ApplicationModel.ResourceCommandState.Hidden => ResourceCommandState.Hidden,
// A newer or malformed state must not terminate WatchResources or become actionable for older clients.
_ => ResourceCommandState.Hidden
};
}
}
View on GitHub (pinned to 25830f84bd)