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
- Log the offending kind value from the error to identify the source
- Align all controllers on the same argo-workflows version
- Regenerate/recreate the sync lock from a valid workflow synchronization reference
- 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
- Never hand-edit encoded lock names or sync state
- Run homogeneous controller versions across replicas
- Round-trip test DecodeLockName/encode in CI
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
- couldn't decode locks for session: %w
- database session is not available for semaphore %s
- failed to initialize semaphore %s: %w
- cannot re-establish %s %q held by workflow %s/%s at startup:
- cannot acquire lock from nil Synchronization
AI-assisted analysis of argoproj/argo-workflows@35bff19146 (2026-09-03).
Data as JSON: /api/errors/a99fca6ac4b3b423.
Report an issue: GitHub.