hashicorp/nomad · error

failed to parse signal: %w

Error message

failed to parse signal: %w

What it means

In Nomad's vault_hook, when a Vault token is renewed and the vault block's change_mode is "signal", the hook parses the configured change_signal via signals.Parse before signaling the task. If the signal string is not a recognized signal name (e.g. on Linux "SIGUSR1", "USR1", or "HUP"), this wrapped error is returned and the token-change handling fails, preventing the task from receiving the new Vault token notification.

Source

Thrown at client/allocrunner/taskrunner/vault_hook.go:271

	}
}

// handleRenewalFailure attempts to get a new Vault token and triggers any change_mode
func (h *vaultHook) handleRenewalFailure(ctx context.Context) (string, time.Duration, error) {
	token, duration, err := h.deriveVaultToken(ctx)
	if err != nil {
		return "", 0, err
	}
	if err := h.writeToken(token); err != nil {
		return "", 0, fmt.Errorf("failed to write Vault token to disk: %w", err)
	}

	var event *structs.TaskEvent
	switch h.vaultBlock.ChangeMode {
	case structs.VaultChangeModeSignal:
		s, err := signals.Parse(h.vaultBlock.ChangeSignal)
		if err != nil {
			return "", 0, fmt.Errorf("failed to parse signal: %w", err)
		}

		event := structs.NewTaskEvent(structs.TaskSignaling).
			SetTaskSignal(s).SetDisplayMessage("Vault: new Vault token acquired")
		if err := h.lifecycle.Signal(event, h.vaultBlock.ChangeSignal); err != nil {
			return "", 0, fmt.Errorf("failed to send signal: %w", err)
		}
	case structs.VaultChangeModeRestart:
		event = structs.NewTaskEvent(structs.TaskRestartSignal).
			SetDisplayMessage("Vault: new Vault token acquired")
		h.lifecycle.Restart(ctx, event, false)
	case structs.VaultChangeModeNoop:
		// True to its name, this is a noop!
	default:
		h.logger.Error("invalid Vault change mode", "mode", h.vaultBlock.ChangeMode)
	}

	h.updater.updatedVaultToken(token)

View on GitHub (pinned to 482b49bf1a)

Solutions

  1. Fix change_signal in the job's vault block to a valid signal name for the target OS (e.g. "SIGUSR1" or "SIGHUP")
  2. Run nomad job validate/plan locally to catch invalid signal names before submission
  3. If the task cannot handle signals, switch change_mode to "restart" or "noop" instead of "signal"
  4. Check signals.Parse / signals.ValidSignals for the platform to confirm the exact accepted spelling

Example fix

// before
vault {
  change_mode   = "signal"
  change_signal = "SIGUSR"
}
// after
vault {
  change_mode   = "signal"
  change_signal = "SIGUSR1"
}
Defensive patterns

Strategy: validation

Validate before calling

// validate job before submit
$ nomad job validate job.nomad.hcl
// ensure signal is valid for the target platform:
// linux: SIGUSR1, SIGHUP, ... windows: 1.0 (only '1.0'/'TERM' style) per docs

Prevention

When it happens

Trigger: A job's vault block sets change_mode = "signal" with a change_signal value that signals.Parse cannot resolve (typo like "SIGNUSR1", unsupported name on the platform, or empty string). The error surfaces from handleRenewalFailure when a renewed token must be delivered to the task.

Common situations: Typo in change_signal in the job HCL; using a Windows-only or Linux-only signal on the other OS; copy-pasting a signal name with an incorrect prefix; Nomad agent running on an OS whose signal table lacks the requested signal.

Understand the failure class

Related errors


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