{"record":{"id":"f079fb984c69a453","repo":"hashicorp/nomad","slug":"failed-to-parse-signal-v","errorCode":null,"errorMessage":"failed to parse signal: %v","messagePattern":"failed to parse signal: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"drivers/docker/driver.go","lineNumber":1903,"sourceCode":"\t\treturn nil, drivers.ErrTaskNotFound\n\t}\n\n\treturn h.Stats(ctx, interval, d.compute)\n}\n\nfunc (d *Driver) TaskEvents(ctx context.Context) (<-chan *drivers.TaskEvent, error) {\n\treturn d.eventer.TaskEvents(ctx)\n}\n\nfunc (d *Driver) SignalTask(taskID string, signal string) error {\n\th, ok := d.tasks.Get(taskID)\n\tif !ok {\n\t\treturn drivers.ErrTaskNotFound\n\t}\n\n\t_, err := signals.Parse(signal)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to parse signal: %v\", err)\n\t}\n\n\t// TODO: review whether we can timeout in this and other Docker API\n\t// calls without breaking the expected client behavior.\n\t// see https://github.com/hashicorp/nomad/issues/9503\n\t_, err = h.dockerClient.ContainerKill(d.ctx, h.containerID, mclient.ContainerKillOptions{Signal: signal})\n\treturn err\n}\n\nfunc (d *Driver) ExecTask(taskID string, cmd []string, timeout time.Duration) (*drivers.ExecTaskResult, error) {\n\th, ok := d.tasks.Get(taskID)\n\tif !ok {\n\t\treturn nil, drivers.ErrTaskNotFound\n\t}\n\n\tif len(cmd) == 0 {\n\t\treturn nil, fmt.Errorf(\"cmd is required, but was empty\")\n\t}","sourceCodeStart":1885,"sourceCodeEnd":1921,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/drivers/docker/driver.go#L1885-L1921","documentation":"The driver's SignalTask method parses the user-supplied signal string with `signals.Parse` before forwarding it to `ContainerKill`. If the string is not a recognized signal name (e.g. SIGTERM) or number, the driver returns this wrapped error and never sends anything to the container. It is a pure input-validation error, not a Docker API failure.","triggerScenarios":"Calling driver.SignalTask(taskID, signal) where `signal` is an unknown name like \"sigterm\" (wrong case), \"TERM15\", \"SIG_KILL\", an empty string, or an out-of-range number.","commonSituations":"Task config `kill_signal` misspelled; API/UI clients sending lowercase \"term\" or \"sigusr1\" variants not in the accepted set; plugins forwarding raw user input.","solutions":["Use a canonical signal name or number: \"SIGTERM\", \"SIGINT\", \"SIGKILL\", \"SIGHUP\", or integer like 9.","Normalize input before calling (e.g. strings.ToUpper + ensure \"SIG\" prefix, or pass a number).","Check the accepted signal list in hashicorp/nomad helper/signals for exact spellings.","Catch the error at the caller and surface the valid-signal list to the user."],"exampleFix":"// before\ndriver.SignalTask(taskID, \"term\")\n// after\ndriver.SignalTask(taskID, \"SIGTERM\")","handlingStrategy":"validation","validationCode":"var validSignals = map[string]bool{\"SIGTERM\": true, \"SIGINT\": true, \"SIGKILL\": true, \"SIGHUP\": true, \"SIGQUIT\": true, \"SIGUSR1\": true, \"SIGUSR2\": true}\nfunc isValidSignal(s string) bool {\n    if n, err := strconv.Atoi(s); err == nil { return n > 0 && n < 65 }\n    return validSignals[strings.ToUpper(s)]\n}\nif !isValidSignal(signal) { return fmt.Errorf(\"invalid signal %q\", signal) }","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always use canonical uppercase \"SIGXXX\" names or numeric signal values.","Keep a whitelist of supported signals in your tooling.","Normalize user input (uppercase, ensure SIG prefix) before passing to the driver."],"tags":["docker","signals","validation"],"backgroundTag":"invalid-signal-name","analyzedSha":"482b49bf1aec006f089bcfc7e632d8f6ac303e5e","analyzedAt":"2026-09-04T07:54:14.808Z","contentChangedAt":"2026-09-04T07:54:14.808Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}