argoproj/argo-workflows · error

invalid lock kind %s when initializing semaphore

Error message

invalid lock kind %s when initializing semaphore

What it means

initializeSemaphore decoded the lock name but the resulting kind is neither configmap nor database, so no semaphore implementation exists and 'invalid lock kind %s when initializing semaphore' is returned. This indicates an unrecognized or corrupted lock kind value reaching the semaphore factory.

Source

Thrown at workflow/sync/sync_manager.go:860

	}
	return nil, nil
}

func (sm *Manager) initializeSemaphore(ctx context.Context, semaphoreName string) (semaphore, error) {
	lock, err := DecodeLockName(ctx, semaphoreName)
	if err != nil {
		return nil, err
	}
	switch lock.getKind() {
	case lockKindConfigMap:
		return newInternalSemaphore(ctx, semaphoreName, sm.nextWorkflow, sm.getSyncLimit, sm.syncLimitCacheTTL)
	case lockKindDatabase:
		if sm.dbInfo.SessionProxy == nil {
			return nil, fmt.Errorf("database session is not available for semaphore %s", semaphoreName)
		}
		return newDatabaseSemaphore(ctx, semaphoreName, lock.getDBKey(), sm.nextWorkflow, sm.dbInfo, sm.syncLimitCacheTTL)
	default:
		return nil, fmt.Errorf("invalid lock kind %s when initializing semaphore", lock.getKind())
	}
}

func (sm *Manager) initializeMutex(ctx context.Context, mutexName string) (semaphore, error) {
	lock, err := DecodeLockName(ctx, mutexName)
	if err != nil {
		return nil, err
	}
	switch lock.getKind() {
	case lockKindMutex:
		return newInternalMutex(mutexName, sm.nextWorkflow), nil
	case lockKindDatabase:
		if sm.dbInfo.SessionProxy == nil {
			return nil, fmt.Errorf("database session is not available for mutex %s", mutexName)
		}
		return newDatabaseMutex(mutexName, lock.getDBKey(), sm.nextWorkflow, sm.dbInfo), nil
	default:
		return nil, fmt.Errorf("invalid lock kind %s when initializing mutex", lock.getKind())

View on GitHub (pinned to 35bff19146)

Solutions

  1. Log the offending kind value from the error to identify the source
  2. Align all controllers on the same argo-workflows version
  3. Regenerate/recreate the sync lock from a valid workflow synchronization reference
  4. Remove the corrupted lock record so it is rebuilt correctly
Defensive patterns

Strategy: type-guard

Validate before calling

lock, err := sync.DecodeLockName(ctx, name)
if err != nil || (lock.GetKind() != sync.LockKindConfigMap && lock.GetKind() != sync.LockKindDatabase) {
    return fmt.Errorf("unsupported lock kind for %q", name)
}

Type guard

func knownLockKind(k sync.LockKind) bool {
    return k == sync.LockKindConfigMap || k == sync.LockKindDatabase
}

Try / catch

if err != nil && strings.Contains(err.Error(), "invalid lock kind") { /* discard corrupted lock, rebuild from spec */ }

Prevention

When it happens

Trigger: DecodeLockName returns a lock whose getKind() hits the default branch — a lock name encoded with an unknown kind constant (corrupted state, hand-edited sync data, or incompatible version).

Common situations: Version skew between controllers sharing sync state; manual edits to sync ConfigMaps; custom or experimental lock kinds from a patched build.

Related errors


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