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

  1. Check the workflow's status for a malformed synchronization entry and fix or re-submit the workflow
  2. Ensure controller and CLI versions match the workflow spec features you use
  3. 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

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


AI-assisted analysis of argoproj/argo-workflows@35bff19146 (2026-09-03). Data as JSON: /api/errors/42df21dba6b78150. Report an issue: GitHub.