argoproj/argo-workflows · error

failed to get current lock holders: %w

Error message

failed to get current lock holders: %w

What it means

After acquiring, tryAcquireImpl reads the authoritative holder list via getCurrentLockHolders to reconcile workflow status; a backend error here aborts the acquire with 'failed to get current lock holders'. Lock state is unknown, so the operation fails rather than risking an inconsistent double-acquire.

Source

Thrown at workflow/sync/sync_manager.go:657

		var newly []*acquiredLock
		for i, lockKey := range lockKeys {
			lock := sm.syncLockMap[lockKey]
			var acquired bool
			var acquireErr error
			acquired, msg, acquireErr = lock.tryAcquire(ctx, holderKey, tx)
			if acquireErr != nil {
				// Surface the underlying error so callers (e.g. TryAcquire's
				// retry loop) can decide whether it is retryable. Transient
				// database errors like PostgreSQL SQLSTATE 40001 must reach
				// the retry detector untouched.
				return false, false, "", failedLockName, nil, acquireErr
			}
			if !acquired {
				return false, false, "", failedLockName, nil, fmt.Errorf("bug: failed to acquire something that should have been checked: %s", msg)
			}
			currentHolders, err := sm.getCurrentLockHolders(ctx, lockKey)
			if err != nil {
				return false, false, "", failedLockName, nil, fmt.Errorf("failed to get current lock holders: %w", err)
			}
			if wf.Status.Synchronization.GetStatus(syncItems[i].getType()).LockAcquired(holderKey, lockKey, currentHolders) {
				updated = true
				newly = append(newly, &acquiredLock{name: lockKey, kind: syncItems[i].getType()})
			}
		}
		return true, updated, msg, failedLockName, newly, nil
	default: // Not all acquirable
		updated := false
		for i, lockKey := range lockKeys {
			currentHolders, err := sm.getCurrentLockHolders(ctx, lockKey)
			if err != nil {
				return false, false, "", failedLockName, nil, fmt.Errorf("failed to get current lock holders: %w", err)
			}
			if wf.Status.Synchronization.GetStatus(syncItems[i].getType()).LockWaiting(holderKey, lockKey, currentHolders) {
				updated = true
			}
		}

View on GitHub (pinned to 35bff19146)

Solutions

  1. Check the wrapped cause: ConfigMap RBAC vs DB connectivity
  2. Retry the operation — often transient (backend hiccup)
  3. Verify the controller's RBAC allows reading sync ConfigMaps
  4. Check DB health for database-backed locks
Defensive patterns

Strategy: retry

Try / catch

if err != nil && strings.Contains(err.Error(), "failed to get current lock holders") {
    if utilerrors.IsTransientErr(ctx, err) { time.Sleep(backoff); retry() }
}

Prevention

When it happens

Trigger: getCurrentLockHolders errors after a successful individual acquire — ConfigMap read/decode failure, DB query failure, or transient backend unavailability for that lockKey.

Common situations: API-server throttling or RBAC denial on ConfigMap reads; Postgres/MySQL outage for DB-backed semaphores; oversized/corrupted sync ConfigMap.

Related errors


AI-assisted analysis of argoproj/argo-workflows@35bff19146 (2026-09-03). Data as JSON: /api/errors/caf5e76f82557854. Report an issue: GitHub.