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
- Fix change_signal in the job's vault block to a valid signal name for the target OS (e.g. "SIGUSR1" or "SIGHUP")
- Run nomad job validate/plan locally to catch invalid signal names before submission
- If the task cannot handle signals, switch change_mode to "restart" or "noop" instead of "signal"
- 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
- Run `nomad job validate` on every job before submission
- Keep a per-OS allowlist of signals your tasks can handle
- Prefer change_mode = "restart" unless the task explicitly handles the signal
- Lint job HCL in CI to catch typos in change_signal
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
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- failed to send signal: %w
- nil vault config
- no signed workload identity available
- plugin not found
- wait config is nil or empty
AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04).
Data as JSON: /api/errors/04cf69ac8b61e174.
Report an issue: GitHub.