{"record":{"id":"42df21dba6b78150","repo":"argoproj/argo-workflows","slug":"cannot-get-lockname-if-not-semaphore-or-mutex","errorCode":null,"errorMessage":"cannot get lockName if not semaphore or mutex","messagePattern":"cannot get lockName if not semaphore or mutex","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"workflow/sync/lock_name.go","lineNumber":91,"sourceCode":"func getMutexLockName(mtx *v1alpha1.Mutex, wfNamespace string) *lockName {\n\tnamespace := mtx.Namespace\n\tif namespace == \"\" {\n\t\tnamespace = wfNamespace\n\t}\n\tif mtx.Database {\n\t\treturn newLockName(namespace, mtx.Name, \"\", lockKindDatabase)\n\t}\n\treturn newLockName(namespace, mtx.Name, \"\", lockKindMutex)\n}\n\nfunc (i *syncItem) lockName(wfNamespace string) (*lockName, error) {\n\tswitch {\n\tcase i.semaphore != nil:\n\t\treturn getSemaphoreLockName(i.semaphore, wfNamespace)\n\tcase i.mutex != nil:\n\t\treturn getMutexLockName(i.mutex, wfNamespace), nil\n\tdefault:\n\t\treturn nil, fmt.Errorf(\"cannot get lockName if not semaphore or mutex\")\n\t}\n}\n\nfunc DecodeLockName(ctx context.Context, name string) (LockName, error) {\n\tlog := logging.RequireLoggerFromContext(ctx)\n\tlog.WithField(\"name\", name).Info(ctx, \"DecodeLockName\")\n\titems := strings.SplitN(name, \"/\", 3)\n\tif len(items) < 3 {\n\t\treturn nil, errors.New(errors.CodeBadRequest, \"Invalid lock key: unknown format\")\n\t}\n\n\tvar lock lockName\n\tkind := lockKind(items[1])\n\tnamespace := items[0]\n\n\tswitch kind {\n\tcase lockKindMutex, lockKindDatabase:\n\t\tlock = lockName{namespace: namespace, kind: kind, resourceName: items[2]}","sourceCodeStart":73,"sourceCodeEnd":109,"githubUrl":"https://github.com/argoproj/argo-workflows/blob/35bff19146f5a6ada77468c431f2624bd577e373/workflow/sync/lock_name.go#L73-L109","documentation":"lockName is the dispatcher over a synchronization item (`i`): it returns the lock identity for a semaphore or a mutex. If the item is neither (both nil), there is no lock to name and this error is returned.","triggerScenarios":"TryAcquire, Release, or getWorkflowSyncLevelByName is called with a SyncItem whose `semaphore` and `mutex` fields are both nil — e.g. a corrupted/partially-written sync item reconstructed from status, or a new synchronization kind handled by generic code but not yet in this switch.","commonSituations":"Hand-edited or migrated workflow status containing malformed synchronization entries; upgrading across Argo versions where a new lock kind isn't recognized by an older code path; bugs in code constructing SyncItems.","solutions":["Check the workflow's status for a malformed synchronization entry and fix or re-submit the workflow","Ensure controller and CLI versions match the workflow spec features you use","If reproducible, report/inspect the code path constructing the SyncItem — the spec should never produce an empty item"],"exampleFix":"// before: item with neither field\n{ }\n// after: item must carry exactly one lock kind\nsynchronization:\n  mutex:\n    name: my-mutex","handlingStrategy":"type-guard","validationCode":"// before constructing/acquiring, ensure the sync item names exactly one kind\nfunc syncItemValid(i *SyncItem) bool {\n    return i != nil && (i.Semaphore != nil) != (i.Mutex != nil)\n}","typeGuard":"func hasLockKind(i *SyncItem) bool {\n    if i == nil { return false }\n    return i.Semaphore != nil || i.Mutex != nil\n}","tryCatchPattern":"err := manager.TryAcquire(ctx, item)\nif err != nil && strings.Contains(err.Error(), \"not semaphore or mutex\") {\n    return fmt.Errorf(\"sync item is malformed; re-submit workflow: %w\", err)\n}","preventionTips":["Never hand-edit workflow status; let the controller own sync state","Upgrade controller and CLI together so sync item shapes match","When adding new lock kinds, extend lockName's switch explicitly"],"tags":["semaphore","mutex","internal-state"],"backgroundTag":"invalid-sync-item","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"}