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

  1. Locate the malformed holder entry in the lock's holder list (workflow status or sync ConfigMap/DB) and remove or correct it
  2. Re-submit the workflow so holds are re-registered with the canonical 'namespace/workflow/node' format
  3. 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

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.