argoproj/argo-workflows · error
failed to marshall claims: %w
Error message
failed to marshall claims: %w
What it means
During SSO RBAC authorization, argo-server's getServiceAccount iterates ServiceAccounts annotated with workflows.argoproj.io/rbac-rule and evaluates each rule against the JSON-serialized OIDC claims. This error is returned when jsonutil.Jsonify(claims) fails to serialize the claims struct to the value map fed into the expr evaluator. In practice the claims struct is always plain JSON-marshalable data, so this almost always indicates an internal/unexpected failure rather than a user config problem; note the serialization is needlessly repeated inside the loop, so a marshal failure blocks matching any rule.
Source
Thrown at server/auth/gatekeeper.go:250
func (s *gatekeeper) getServiceAccount(claims *authTypes.Claims, namespace string) (*corev1.ServiceAccount, error) {
list, err := s.cache.ServiceAccountLister.ServiceAccounts(namespace).List(labels.Everything())
if err != nil {
return nil, fmt.Errorf("failed to list SSO RBAC service accounts: %w", err)
}
var serviceAccounts []*corev1.ServiceAccount
for _, serviceAccount := range list {
_, ok := serviceAccount.Annotations[common.AnnotationKeyRBACRule]
if !ok {
continue
}
serviceAccounts = append(serviceAccounts, serviceAccount)
}
sort.Slice(serviceAccounts, func(i, j int) bool { return precedence(serviceAccounts[i]) > precedence(serviceAccounts[j]) })
for _, serviceAccount := range serviceAccounts {
rule := serviceAccount.Annotations[common.AnnotationKeyRBACRule]
v, err := jsonutil.Jsonify(claims)
if err != nil {
return nil, fmt.Errorf("failed to marshall claims: %w", err)
}
allow, err := argoexpr.EvalBool(rule, v)
if err != nil {
return nil, fmt.Errorf("failed to evaluate rule: %w", err)
}
if !allow {
continue
}
return serviceAccount, nil
}
return nil, fmt.Errorf("no service account rule matches")
}
func (s *gatekeeper) canDelegateRBACToRequestNamespace(req any) bool {
if s.namespaced || os.Getenv("SSO_DELEGATE_RBAC_TO_NAMESPACE") != "true" {
return false
}
namespace := getNamespace(req)View on GitHub (pinned to 35bff19146)
Solutions
- Restart argo-server and retry the request; if persistent, capture the full error (wrapped %w cause) and file an issue with server logs.
- Check that your argo-server image is an unmodified official release; custom patches to server/auth or serviceaccount claims types are the most likely culprit.
- Upgrade to a recent argo-workflows release, since the claims-to-JSON path has been refactored over versions.
Defensive patterns
Strategy: try-catch
Try / catch
// client side: gRPC unauthenticated error
_, err := client.WorkflowService.ListWorkflows(ctx, req)
if err != nil {
if st, ok := status.FromError(err); ok && st.Code() == codes.Unauthenticated && strings.Contains(st.Message(), "not allowed") {
// surface server logs; report bug if 'failed to marshall claims'
}
return err
} Prevention
- Run unmodified official argo-server images
- Keep argo-server upgraded; this path is an internal invariant, so treat occurrences as bugs
- Capture the wrapped cause from server logs before retrying
When it happens
Trigger: An SSO-authenticated gRPC/HTTP request with RBAC enabled reaches rbacAuthorization -> getServiceAccount, and jsonutil.Jsonify(*authTypes.Claims) returns an error while preparing the expression input for a ServiceAccount's rbac-rule annotation.
Common situations: Practically only seen with a corrupted/non-standard claims object, a custom or forked build that changed the Claims type, or tampered middleware state; end users rarely hit this since authTypes.Claims is a simple marshalable struct.
Related errors
- failed to list SSO RBAC service accounts: %w
- failed to evaluate rule: %w
- no service account rule matches
- failed to get service account secret: %w
- not implemented
AI-assisted analysis of argoproj/argo-workflows@35bff19146 (2026-09-03).
Data as JSON: /api/errors/8417174cf953c83e.
Report an issue: GitHub.