{"record":{"id":"533f8811e5a82d8a","repo":"microsoft/aspire","slug":"unexpected-icon-variant-iconvariant","errorCode":null,"errorMessage":"Unexpected icon variant: {iconVariant}","messagePattern":"Unexpected icon variant: (.+?)","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/Aspire.Hosting/Dashboard/proto/Partials.cs","lineNumber":166,"sourceCode":"        {\n            return healthStatus switch\n            {\n                Microsoft.Extensions.Diagnostics.HealthChecks.HealthStatus.Healthy => HealthStatus.Healthy,\n                Microsoft.Extensions.Diagnostics.HealthChecks.HealthStatus.Degraded => HealthStatus.Degraded,\n                Microsoft.Extensions.Diagnostics.HealthChecks.HealthStatus.Unhealthy => HealthStatus.Unhealthy,\n                _ => throw new InvalidOperationException(\"Unknown health status: \" + healthStatus),\n            };\n        }\n    }\n\n    private static IconVariant MapIconVariant(Hosting.ApplicationModel.IconVariant? iconVariant)\n    {\n        return iconVariant switch\n        {\n            Hosting.ApplicationModel.IconVariant.Regular => IconVariant.Regular,\n            Hosting.ApplicationModel.IconVariant.Filled => IconVariant.Filled,\n            null => IconVariant.Regular,\n            _ => throw new InvalidOperationException(\"Unexpected icon variant: \" + iconVariant)\n        };\n    }\n\n    private static ResourceCommandState MapCommandState(Hosting.ApplicationModel.ResourceCommandState state)\n    {\n        return state switch\n        {\n            Hosting.ApplicationModel.ResourceCommandState.Enabled => ResourceCommandState.Enabled,\n            Hosting.ApplicationModel.ResourceCommandState.Disabled => ResourceCommandState.Disabled,\n            Hosting.ApplicationModel.ResourceCommandState.Hidden => ResourceCommandState.Hidden,\n            // A newer or malformed state must not terminate WatchResources or become actionable for older clients.\n            _ => ResourceCommandState.Hidden\n        };\n    }\n}\n","sourceCodeStart":148,"sourceCodeEnd":182,"githubUrl":"https://github.com/microsoft/aspire/blob/25830f84bd145686607ad00c057b3f84e2e51d43/src/Aspire.Hosting/Dashboard/proto/Partials.cs#L148-L182","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\nvar variant = (IconVariant)storedValue;\n// after\nvar variant = Enum.IsDefined(typeof(IconVariant), storedValue) ? (IconVariant)storedValue : IconVariant.Regular;","handlingStrategy":"try-catch","validationCode":"if (iconVariant is not (IconVariant.Regular or IconVariant.Filled or null))\n{\n    iconVariant = IconVariant.Regular;\n}","typeGuard":"bool IsKnownIconVariant(IconVariant? v) => v is null or IconVariant.Regular or IconVariant.Filled;","tryCatchPattern":"try\n{\n    protoVariant = MapIconVariant(iconVariant);\n}\ncatch (InvalidOperationException ex) when (ex.Message.StartsWith(\"Unexpected icon variant\"))\n{\n    protoVariant = IconVariant.Regular; // default variant\n}","preventionTips":["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"],"tags":["dashboard","enum","icon"],"backgroundTag":"invalid-enum-value","analyzedSha":"25830f84bd145686607ad00c057b3f84e2e51d43","analyzedAt":"2026-09-16T11:10:06.193Z","contentChangedAt":"2026-09-16T11:10:06.193Z","schemaVersion":2},"datasetVersion":"2026-09-21T09:17:21.228Z"}