argoproj/argo-workflows · critical
database session is not available for semaphore %s
Error message
database session is not available for semaphore %s
What it means
initializeSemaphore builds a semaphore for a decoded lock; for lockKindDatabase it requires the manager's DB session proxy and returns 'database session is not available for semaphore <name>' when it is nil. Called during prepAcquire, this blocks acquisition of any DB-backed semaphore when persistence is not configured.
Source
Thrown at workflow/sync/sync_manager.go:856
func (sm *Manager) getCurrentLockHolders(ctx context.Context, lock string) ([]string, error) {
if concurrency, ok := sm.syncLockMap[lock]; ok {
return concurrency.getCurrentHolders(ctx)
}
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)View on GitHub (pinned to 35bff19146)
Solutions
- Enable synchronization DB persistence in the controller configuration
- Verify DB credentials/connectivity so SessionProxy initializes at startup
- Restart the controller after fixing persistence config
- Convert the semaphore to ConfigMap-based if DB sync is unnecessary
Defensive patterns
Strategy: validation
Validate before calling
lock, _ := sync.DecodeLockName(ctx, key)
if lock.GetKind() == sync.LockKindDatabase && !dbSessionReady(manager) {
return errors.New("DB-backed semaphore requires configured sync persistence")
} Type guard
func canUseDBLock(sm *sync.Manager) bool { return sm != nil && sm.DBInfo != nil && sm.DBInfo.SessionProxy != nil } Try / catch
if err != nil && strings.Contains(err.Error(), "database session is not available for semaphore") { /* configure persistence, requeue */ } Prevention
- Health-check the sync DB session at controller startup
- Use readiness probes that reflect sync DB availability
- Keep persistence config and workflow sync usage in sync
When it happens
Trigger: prepAcquire resolves a lock decoded as lockKindDatabase while sm.dbInfo.SessionProxy is nil — DB-backed sync config exists but the controller has no sync DB session (persistence disabled or DB down at init).
Common situations: Deploying workflows with SQL-backed synchronization on a controller without DB persistence; wrong DB credentials so the session proxy never initialized; DB lost after controller start.
Related errors
- failed to initialize semaphore %s: %w
- synchronization database session is not available
- failed to get current lock holders: %w
- invalid lock kind %s when initializing semaphore
- invalid uid
AI-assisted analysis of argoproj/argo-workflows@35bff19146 (2026-09-03).
Data as JSON: /api/errors/eec38ad28253b77e.
Report an issue: GitHub.