{"record":{"id":"d3ea1e0c7ba80358","repo":"argoproj/argo-workflows","slug":"database-session-is-not-available-for-mutex-s","errorCode":null,"errorMessage":"database session is not available for mutex %s","messagePattern":"database session is not available for mutex (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"workflow/sync/sync_manager.go","lineNumber":874,"sourceCode":"\t\t\treturn nil, fmt.Errorf(\"database session is not available for semaphore %s\", semaphoreName)\n\t\t}\n\t\treturn newDatabaseSemaphore(ctx, semaphoreName, lock.getDBKey(), sm.nextWorkflow, sm.dbInfo, sm.syncLimitCacheTTL)\n\tdefault:\n\t\treturn nil, fmt.Errorf(\"invalid lock kind %s when initializing semaphore\", lock.getKind())\n\t}\n}\n\nfunc (sm *Manager) initializeMutex(ctx context.Context, mutexName string) (semaphore, error) {\n\tlock, err := DecodeLockName(ctx, mutexName)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tswitch lock.getKind() {\n\tcase lockKindMutex:\n\t\treturn newInternalMutex(mutexName, sm.nextWorkflow), nil\n\tcase lockKindDatabase:\n\t\tif sm.dbInfo.SessionProxy == nil {\n\t\t\treturn nil, fmt.Errorf(\"database session is not available for mutex %s\", mutexName)\n\t\t}\n\t\treturn newDatabaseMutex(mutexName, lock.getDBKey(), sm.nextWorkflow, sm.dbInfo), nil\n\tdefault:\n\t\treturn nil, fmt.Errorf(\"invalid lock kind %s when initializing mutex\", lock.getKind())\n\t}\n}\n\nfunc (sm *Manager) backgroundNotifier(ctx context.Context, period *int) {\n\tsm.log.WithField(\"pollInterval\", syncdb.SecondsToDurationWithDefault(period, syncdb.DefaultDBHeartbeatSeconds)).\n\t\tInfo(ctx, \"Starting background notification for sync locks\")\n\tgo wait.UntilWithContext(ctx, func(_ context.Context) {\n\t\tsm.lock.Lock()\n\t\tfor _, lock := range sm.syncLockMap {\n\t\t\tlock.probeWaiting(ctx)\n\t\t}\n\t\tsm.lock.Unlock()\n\t},\n\t\tsyncdb.SecondsToDurationWithDefault(period, syncdb.DefaultDBPollSeconds),","sourceCodeStart":856,"sourceCodeEnd":892,"githubUrl":"https://github.com/argoproj/argo-workflows/blob/35bff19146f5a6ada77468c431f2624bd577e373/workflow/sync/sync_manager.go#L856-L892","documentation":"The sync Manager can only create a database-backed mutex when a database session proxy has been configured on the manager (sm.dbInfo.SessionProxy). If a sync/mutex resource is declared with kind database but the controller has no DB-backed sync configured, initialization fails. This prevents silently using a mutex that would have no persistent backing.","triggerScenarios":"A workflow references a mutex/sync lock whose ConfigMap-declared kind is 'database' while the workflow-controller was started without database sync configuration (syncConfig with a DB connection), so sm.dbInfo.SessionProxy is nil when initializeMutex runs via prepAcquire.","commonSituations":"Operators switch a lock's kind from configmap to database without updating the controller's sync database configuration; fresh deployments missing the sync DB configmap/DB connection; kind misconfiguration in the workflow's synchronize section.","solutions":["Configure database-backed sync on the workflow-controller (set the sync DB config / syncConfig so dbInfo.SessionProxy is populated) and restart the controller","Change the mutex/lock kind from 'database' back to 'configmap' in the sync ConfigMap if DB sync is not intended","Verify the sync database is reachable and the controller logs show successful DB session setup before submitting workflows"],"exampleFix":"// before (controller lacks DB sync, workflow uses database mutex)\nsynchronize: { mutex: { name: mydbmutex } }  // kind: database\n// after (either fix controller config or use configmap lock)\nsynchronize: { mutex: { name: mymutex } }  // with kind: configmap in sync ConfigMap","handlingStrategy":"validation","validationCode":"// before submitting, confirm the sync DB config is present\nkind := getSyncLockKind(configMap, lockName)\nif kind == \"database\" && controllerSyncDBConfig == nil {\n    return fmt.Errorf(\"database mutex %s requires controller sync DB configuration\", lockName)\n}","typeGuard":"func isDatabaseSyncConfigured(sm *sync.Manager) bool {\n    return sm != nil && sm.DBInfo != nil && sm.DBInfo.SessionProxy != nil\n}","tryCatchPattern":"err := wf.Wait(ctx)\nif err != nil && strings.Contains(err.Error(), \"database session is not available for mutex\") {\n    // fall back to configmap-based mutex or alert operator to enable DB sync\n}","preventionTips":["Keep sync DB configuration and lock kind declarations in the same deployment tooling so they ship together","Lint workflow synchronize blocks against the controller's actual sync configuration","Use configmap locks unless DB-backed durability is explicitly required"],"tags":["sync","mutex","database","configuration"],"backgroundTag":"missing-database-session","analyzedSha":"35bff19146f5a6ada77468c431f2624bd577e373","analyzedAt":"2026-09-03T19:34:35.908Z","contentChangedAt":"2026-09-03T19:34:35.908Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}