argoproj/argo-workflows · error
invalid holderkey format
Error message
invalid holderkey format
What it means
getWorkflowKey requires at least '<namespace>/<workflow>' in the holder key (split on '/' must yield >= 2 items). A malformed key without a slash cannot be reduced to a workflow identity, so this error is returned from CheckWorkflowExistence's holder scan.
Source
Thrown at workflow/sync/sync_manager.go:114
log: log,
}
log.WithField("dbConfigured", sm.dbInfo.SessionProxy != nil).Info(ctx, "Sync manager initialized")
sm.dbInfo.Migrate(ctx)
if sm.dbInfo.SessionProxy != nil {
sm.backgroundNotifier(ctx, config.PollSeconds)
sm.dbControllerHeartbeat(ctx, config.HeartbeatSeconds)
}
return sm
}
func (sm *Manager) getWorkflowKey(key string) (string, error) {
if key == "" {
return "", fmt.Errorf("holderkey is empty")
}
items := strings.Split(key, "/")
if len(items) < 2 {
return "", fmt.Errorf("invalid holderkey format")
}
return fmt.Sprintf("%s/%s", items[0], items[1]), nil
}
func (sm *Manager) CheckWorkflowExistence(ctx context.Context) {
defer runtimeutil.HandleCrashWithContext(ctx, runtimeutil.PanicHandlers...)
sm.lock.Lock()
defer sm.lock.Unlock()
sm.log.Debug(ctx, "Check the workflow existence")
for _, lock := range sm.syncLockMap {
holders, err := lock.getCurrentHolders(ctx)
if err != nil {
sm.log.WithError(err).Error(ctx, "failed to get current lock holders")
continue
}
pending, err := lock.getCurrentPending(ctx)View on GitHub (pinned to 35bff19146)
Solutions
- Locate the malformed holder entry in the lock's holder list (workflow status or sync ConfigMap/DB) and remove or correct it
- Re-submit the workflow so holds are re-registered with the canonical 'namespace/workflow/node' format
- Verify all controller/CLI components run compatible versions so holder-key formats agree
Example fix
// before: wrong format
holderKey := wf.Name
// after: canonical namespace/workflow/node
holderKey := fmt.Sprintf("%s/%s/%s", wf.Namespace, wf.Name, nodeName) Defensive patterns
Strategy: validation
Validate before calling
func holderKeyFormatOK(key string) bool {
parts := strings.Split(key, "/")
return len(parts) >= 2 && parts[0] != "" && parts[1] != ""
} Type guard
func isWellFormedHolderKey(s string) bool {
return strings.Count(s, "/") >= 1 && !strings.HasPrefix(s, "/")
} Try / catch
exists := sm.CheckWorkflowExistence(ctx) // reports holder-key errors
if err != nil && strings.Contains(err.Error(), "invalid holderkey format") {
return fmt.Errorf("purge malformed holder entry: %w", err)
} Prevention
- Use the canonical 'namespace/workflow/node' key format everywhere
- Clean stale holder entries after version upgrades
- Don't invent custom key formats for sync APIs
When it happens
Trigger: A holder key like 'default-mywf-mynode' or 'mynode' (no '/' separators) is encountered while checking lock holders — e.g. a holder registered with a wrong-format key instead of namespace/workflow/node.
Common situations: Custom keys passed to synchronization APIs; state written by a different Argo version with a different holder-key format; manual edits to sync ConfigMaps/DB rows.
Related errors
AI-assisted analysis of argoproj/argo-workflows@35bff19146 (2026-09-03).
Data as JSON: /api/errors/8eb0af19ac0d2108.
Report an issue: GitHub.