{"record":{"id":"ef2adef61a49e326","repo":"argoproj/argo-workflows","slug":"cannot-acquire-lock-from-nil-synchronization","errorCode":null,"errorMessage":"cannot acquire lock from nil Synchronization","messagePattern":"cannot acquire lock from nil Synchronization","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"workflow/sync/sync_manager.go","lineNumber":455,"sourceCode":"\t\t\t\t}\n\t\t\t\tif reason != \"\" {\n\t\t\t\t\tstale(reason)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\tsm.log.Info(ctx, \"Sync manager initialized successfully\")\n\treturn staleHolds, nil\n}\n\n// TryAcquire tries to acquire the lock from semaphore.\n// It returns status of acquiring a lock , status of Workflow status updated, waiting message if lock is not available, the failed lock, and any error encountered\nfunc (sm *Manager) TryAcquire(ctx context.Context, wf *wfv1.Workflow, nodeName string, syncLockRef *wfv1.Synchronization) (bool, bool, string, string, error) {\n\tsm.lock.Lock()\n\tdefer sm.lock.Unlock()\n\n\tif syncLockRef == nil {\n\t\treturn false, false, \"\", \"\", fmt.Errorf(\"cannot acquire lock from nil Synchronization\")\n\t}\n\n\tfailedLockName := \"\"\n\tsyncItems, err := allSyncItems(syncLockRef)\n\tif err != nil {\n\t\treturn false, false, \"\", failedLockName, fmt.Errorf(\"requested configuration is invalid: %w\", err)\n\t}\n\tholderKey := getHolderKey(wf, nodeName)\n\n\tlockKeys := make([]string, len(syncItems))\n\tfor i, syncItem := range syncItems {\n\t\tsyncLockName, lockNameErr := syncItem.lockName(wf.Namespace)\n\t\tif lockNameErr != nil {\n\t\t\treturn false, false, \"\", failedLockName, fmt.Errorf(\"requested configuration is invalid: %w\", lockNameErr)\n\t\t}\n\t\tsm.log.WithField(\"syncLockName\", syncLockName).Info(ctx, \"TryAcquire\")\n\t\tlockKeys[i] = syncLockName.String(ctx)\n\t}","sourceCodeStart":437,"sourceCodeEnd":473,"githubUrl":"https://github.com/argoproj/argo-workflows/blob/35bff19146f5a6ada77468c431f2624bd577e373/workflow/sync/sync_manager.go#L437-L473","documentation":"Manager.TryAcquire requires a non-nil *wfv1.Synchronization describing what to acquire. A nil reference means the caller passed no synchronization/mutex spec at all, so the call is rejected immediately. This is a programming/configuration bug in the caller, not a transient condition.","triggerScenarios":"Calling TryAcquire with syncLockRef == nil, e.g. when the node's template declares neither semaphore nor mutex but the operator loop still invokes TryAcquire.","commonSituations":"Custom controller code calling TryAcquire without checking whether the template declares a synchronization; partial YAML unmarshal dropping the synchronization field.","solutions":["Check the template declares synchronization.semaphore or synchronization.mutex before calling TryAcquire","Skip the TryAcquire call when the node has no synchronization reference","Verify the workflow spec was fully unmarshaled with no dropped fields"],"exampleFix":"// before\nok, _, msg, lock, err := sm.TryAcquire(ctx, wf, nodeName, nil)\n// after\nif tmpl.Synchronization != nil {\n    ok, _, msg, lock, err := sm.TryAcquire(ctx, wf, nodeName, tmpl.Synchronization)\n}","handlingStrategy":"validation","validationCode":"if syncRef == nil {\n    // node has no synchronization; do not call TryAcquire\n    return\n}","typeGuard":"func hasSync(tmpl *wfv1.Template) bool {\n    return tmpl != nil && tmpl.Synchronization != nil\n}","tryCatchPattern":"if _, _, _, _, err := sm.TryAcquire(ctx, wf, node, ref); err != nil && strings.Contains(err.Error(), \"nil Synchronization\") { /* skip: no sync declared */ }","preventionTips":["Never call TryAcquire without a resolved Synchronization object","Validate workflow specs with workflow/validate before processing","Unit-test operators against templates without synchronization"],"tags":["argo-workflows","sync","nil-argument","api-misuse"],"backgroundTag":"nil-argument","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"}