argoproj/argo-workflows · error
cannot get lockName if not semaphore or mutex
Error message
cannot get lockName if not semaphore or mutex
What it means
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.
Source
Thrown at workflow/sync/lock_name.go:91
func getMutexLockName(mtx *v1alpha1.Mutex, wfNamespace string) *lockName {
namespace := mtx.Namespace
if namespace == "" {
namespace = wfNamespace
}
if mtx.Database {
return newLockName(namespace, mtx.Name, "", lockKindDatabase)
}
return newLockName(namespace, mtx.Name, "", lockKindMutex)
}
func (i *syncItem) lockName(wfNamespace string) (*lockName, error) {
switch {
case i.semaphore != nil:
return getSemaphoreLockName(i.semaphore, wfNamespace)
case i.mutex != nil:
return getMutexLockName(i.mutex, wfNamespace), nil
default:
return nil, fmt.Errorf("cannot get lockName if not semaphore or mutex")
}
}
func DecodeLockName(ctx context.Context, name string) (LockName, error) {
log := logging.RequireLoggerFromContext(ctx)
log.WithField("name", name).Info(ctx, "DecodeLockName")
items := strings.SplitN(name, "/", 3)
if len(items) < 3 {
return nil, errors.New(errors.CodeBadRequest, "Invalid lock key: unknown format")
}
var lock lockName
kind := lockKind(items[1])
namespace := items[0]
switch kind {
case lockKindMutex, lockKindDatabase:
lock = lockName{namespace: namespace, kind: kind, resourceName: items[2]}View on GitHub (pinned to 35bff19146)
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
Example fix
// before: item with neither field
{ }
// after: item must carry exactly one lock kind
synchronization:
mutex:
name: my-mutex Defensive patterns
Strategy: type-guard
Validate before calling
// before constructing/acquiring, ensure the sync item names exactly one kind
func syncItemValid(i *SyncItem) bool {
return i != nil && (i.Semaphore != nil) != (i.Mutex != nil)
} Type guard
func hasLockKind(i *SyncItem) bool {
if i == nil { return false }
return i.Semaphore != nil || i.Mutex != nil
} Try / catch
err := manager.TryAcquire(ctx, item)
if err != nil && strings.Contains(err.Error(), "not semaphore or mutex") {
return fmt.Errorf("sync item is malformed; re-submit workflow: %w", err)
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- can't find podInfo for podName %q
- can't find template with name %q
- failed to initialize semaphore %s: %w
- could not verify hold on %s for %s: %w
- hold on %s for %s is not present in the database
AI-assisted analysis of argoproj/argo-workflows@35bff19146 (2026-09-03).
Data as JSON: /api/errors/42df21dba6b78150.
Report an issue: GitHub.