{"record":{"id":"b5672d7893594185","repo":"microsoft/aspire","slug":"roles-i-is-not-a-valid-nameof-azuresignalrrole-value","errorCode":null,"errorMessage":"'{roles[i]}' is not a valid {nameof(AzureSignalRRole)} value.","messagePattern":"'(.+?)' is not a valid (.+?) value\\.","errorType":"validation","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"src/Aspire.Hosting.Azure.SignalR/AzureSignalRExtensions.cs","lineNumber":241,"sourceCode":"        this IResourceBuilder<T> builder,\n        IResourceBuilder<AzureSignalRResource> target,\n        params AzureSignalRRole[] roles)\n        where T : IResource\n    {\n        if (roles is null || roles.Length == 0)\n        {\n            return builder.WithRoleAssignments(target, Array.Empty<SignalRBuiltInRole>());\n        }\n\n        var builtInRoles = new SignalRBuiltInRole[roles.Length];\n        for (var i = 0; i < roles.Length; i++)\n        {\n            builtInRoles[i] = roles[i] switch\n            {\n                AzureSignalRRole.SignalRContributor => SignalRBuiltInRole.SignalRContributor,\n                AzureSignalRRole.SignalRAppServer => SignalRBuiltInRole.SignalRAppServer,\n                AzureSignalRRole.SignalRRestApiOwner => SignalRBuiltInRole.SignalRRestApiOwner,\n                _ => throw new ArgumentException($\"'{roles[i]}' is not a valid {nameof(AzureSignalRRole)} value.\", nameof(roles))\n            };\n        }\n\n        return builder.WithRoleAssignments(target, builtInRoles);\n    }\n}\n","sourceCodeStart":223,"sourceCodeEnd":248,"githubUrl":"https://github.com/microsoft/aspire/blob/25830f84bd145686607ad00c057b3f84e2e51d43/src/Aspire.Hosting.Azure.SignalR/AzureSignalRExtensions.cs#L223-L248","documentation":"WithRoleAssignments for Azure SignalR throws ArgumentException when an element of the roles array does not map to a known AzureSignalRRole. The extension only accepts the defined enum values (SignalRContributor, SignalRAppServer, SignalRRestApiOwner) and validates each switch arm.","triggerScenarios":"Calling WithRoleAssignments with a roles array containing an out-of-range cast (e.g. (AzureSignalRRole)99) or an undefined enum member, typically at index i reported in the message.","commonSituations":"Casting raw ints from configuration into the enum; reading role names from config and parsing to enum without validation; library version differences where a role value no longer exists.","solutions":["Use only defined AzureSignalRRole values: SignalRContributor, SignalRAppServer, SignalRRestApiOwner.","Parse role names with Enum.TryParse and reject undefined values before calling WithRoleAssignments.","Check the roles[i] value named in the exception message and remove or correct it."],"exampleFix":"// before\nvar role = (AzureSignalRRole)int.Parse(config[\"Role\"]); // may be undefined\nsignalr.WithRoleAssignments(app, role);\n\n// after\nif (!Enum.TryParse<AzureSignalRRole>(config[\"Role\"], out var role) || !Enum.IsDefined(role))\n{\n    throw new InvalidOperationException($\"Unknown SignalR role: {config[\"Role\"]}\");\n}\nsignalr.WithRoleAssignments(app, role);","handlingStrategy":"validation","validationCode":"foreach (var role in roles) { if (!Enum.IsDefined(typeof(AzureSignalRRole), role)) throw new InvalidOperationException($\"Role {role} is not a defined AzureSignalRRole.\"); }","typeGuard":"static bool IsValidSignalRRole(AzureSignalRRole role) => Enum.IsDefined(typeof(AzureSignalRRole), role);","tryCatchPattern":"try { builder.WithRoleAssignments(target, roles); }\ncatch (ArgumentException ex) { /* log ex.Message; fix role values */ }","preventionTips":["Never cast arbitrary ints to the enum.","Parse role names with Enum.TryParse plus Enum.IsDefined.","Keep role sources in code, not unvalidated configuration."],"tags":["enum","argument","azure-signalr","role-assignment"],"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"}