hashicorp/nomad · error

can only use change_signal=%q with change_mode=%q

Error message

can only use change_signal=%q with change_mode=%q

What it means

WorkloadIdentity.Validate returns this error when ChangeSignal is set while ChangeMode is empty, "noop", or "restart". change_signal only makes sense with change_mode = "signal"; otherwise the signal would never be delivered, so Nomad flags the combination as invalid.

Source

Thrown at nomad/structs/workload_id.go:473

	var mErr multierror.Error

	if !validIdentityName.MatchString(wi.Name) {
		err := fmt.Errorf("invalid name %q. Must match regex %s", wi.Name, validIdentityName)
		mErr.Errors = append(mErr.Errors, err)
	}

	for i, aud := range wi.Audience {
		if aud == "" {
			mErr.Errors = append(mErr.Errors, fmt.Errorf("an empty string is an invalid audience (%d)", i+1))
		}
	}

	switch wi.ChangeMode {
	case "", WIChangeModeNoop, WIChangeModeRestart:
		// Treat "" as noop. Make sure signal isn't set.
		if wi.ChangeSignal != "" {
			mErr.Errors = append(mErr.Errors, fmt.Errorf("can only use change_signal=%q with change_mode=%q",
				wi.ChangeSignal, WIChangeModeSignal))
		}
	case WIChangeModeSignal:
		if wi.ChangeSignal == "" {
			mErr.Errors = append(mErr.Errors, fmt.Errorf("change_signal must be specified when using change_mode=%q", WIChangeModeSignal))
		}
	default:
		// Unknown change_mode
		mErr.Errors = append(mErr.Errors, fmt.Errorf("invalid change_mode: %s", wi.ChangeMode))
	}

	if wi.TTL > 0 && (wi.Name == "" || wi.Name == WorkloadIdentityDefaultName) {
		mErr.Errors = append(mErr.Errors, fmt.Errorf("ttl for default identity not yet supported"))
	}

	if wi.TTL < 0 {
		mErr.Errors = append(mErr.Errors, fmt.Errorf("ttl must be >= 0"))
	}

View on GitHub (pinned to 482b49bf1a)

Solutions

  1. Set change_mode = "signal" so the change_signal is actually used.
  2. Or remove the change_signal field if you intend noop/restart behavior.
  3. Validate the full identity locally — the error names both the signal and the required mode.

Example fix

// before
change_mode = "restart"
change_signal = "SIGHUP"
// after
change_mode = "signal"
change_signal = "SIGHUP"
Defensive patterns

Strategy: validation

Validate before calling

if wi.ChangeSignal != "" && wi.ChangeMode != "signal" {
    return fmt.Errorf("change_signal requires change_mode = signal")
}

Prevention

When it happens

Trigger: Validate() on a WorkloadIdentity where ChangeSignal != "" but ChangeMode is "", WIChangeModeNoop, or WIChangeModeRestart — e.g. a job spec with change_signal = "SIGHUP" but no (or a non-signal) change_mode.

Common situations: Copying a signal-handling identity block but changing change_mode to restart; assuming a signal defaults to signal mode; leftover change_signal after removing change_mode = "signal".

Related errors


AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04). Data as JSON: /api/errors/acc7c4d3a92bd77a. Report an issue: GitHub.