argoproj/argo-workflows · error
group name %v was not a string
Error message
group name %v was not a string
What it means
GetCustomGroup was iterating the custom claim's array but one element is not a string, so it cannot become a group name. The message prints the offending element; the whole extraction aborts rather than skipping it.
Source
Thrown at server/auth/types/claims.go:81
// GetCustomGroup is responsible for extracting groups based on the
// provided custom claim key
func (c *Claims) GetCustomGroup(customKeyName string) ([]string, error) {
groups, ok := c.RawClaim[customKeyName]
if !ok {
return nil, fmt.Errorf("no claim found for key: %v", customKeyName)
}
sliceInterface, ok := groups.([]any)
if !ok {
return nil, fmt.Errorf("expected an array, got %v", groups)
}
newSlice := []string{}
for _, a := range sliceInterface {
val, ok := a.(string)
if !ok {
return nil, fmt.Errorf("group name %v was not a string", a)
}
newSlice = append(newSlice, val)
}
return newSlice, nil
}
func (c *Claims) GetUserInfoGroups(ctx context.Context, httpClient HTTPClient, accessToken, issuer, userInfoPath string) ([]string, error) {
url := fmt.Sprintf("%s%s", issuer, userInfoPath)
request, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
if err != nil {
return nil, err
}
bearer := fmt.Sprintf("Bearer %s", accessToken)
request.Header.Set("Authorization", bearer)
View on GitHub (pinned to 35bff19146)
Solutions
- Configure the IdP mapper to emit plain string group names
- Filter/null-strip the claim on the provider side so only strings remain
- Pick a different claim key that contains simple string arrays
- If you control the code, coerce/skip non-string elements instead of erroring
Example fix
// before
{ "groups": [123, "team-a"] }
// after
{ "groups": ["123", "team-a"] } Defensive patterns
Strategy: type-guard
Validate before calling
for _, e := range claims.RawClaim[key].([]any) {
if _, ok := e.(string); !ok { /* non-string element: fix mapper */ }
} Type guard
func isStringSlice(v any) ([]string, bool) {
arr, ok := v.([]any)
if !ok { return nil, false }
out := make([]string, 0, len(arr))
for _, e := range arr {
s, ok := e.(string)
if !ok { return nil, false }
out = append(out, s)
}
return out, true
} Try / catch
groups, err := claims.GetCustomGroup(key)
if err != nil {
return fmt.Errorf("group claim has non-string members: %w", err)
} Prevention
- Configure mappers to emit flat string arrays (no objects/nulls)
- Strip null/empty entries provider-side
- Test with users in zero, one, and many groups
- Validate token claims in an integration test fixture
When it happens
Trigger: HandleCallback extracts groups where the claim array contains numbers, booleans, nested objects, or nulls — e.g. an IdP emitting group objects like [{"id":"g1"}] instead of plain strings.
Common situations: Keycloak/Okta mappers that emit structured group representations; null entries from partially-populated attributes; numeric group IDs.
Related errors
- expected an array, got %v
- no claim found for key: %v
- failed to load system cert pool: %w
- failed to append certificates from PEM string
- not implemented
AI-assisted analysis of argoproj/argo-workflows@35bff19146 (2026-09-03).
Data as JSON: /api/errors/222cbeb047015062.
Report an issue: GitHub.