hashicorp/nomad · error
unsupported signal type: %q
Error message
unsupported signal type: %q
What it means
grpcExecutorClient.Signal only accepts os.Signal values that are syscall.Signal (integer-numbered Unix/Windows signals). This error means the caller passed a signal implementation that cannot be represented as a syscall.Signal, so it cannot be serialized into the gRPC SignalRequest.
Source
Thrown at drivers/shared/executor/grpc_client.go:172
stats, err := drivers.TaskStatsFromProto(resp.Stats)
if err != nil {
c.logger.Error("failed to decode stats from RPC", "error", err, "stats", resp.Stats)
continue
}
select {
case ch <- stats:
case <-ctx.Done():
return
}
}
}
func (c *grpcExecutorClient) Signal(s os.Signal) error {
ctx := context.Background()
sig, ok := s.(syscall.Signal)
if !ok {
return fmt.Errorf("unsupported signal type: %q", s.String())
}
req := &proto.SignalRequest{
Signal: int32(sig),
}
if _, err := c.client.Signal(ctx, req); err != nil {
return err
}
return nil
}
func (c *grpcExecutorClient) Exec(deadline time.Time, cmd string, args []string) ([]byte, int, error) {
ctx := context.Background()
pbDeadline, err := ptypes.TimestampProto(deadline)
if err != nil {
return nil, 0, err
}
req := &proto.ExecRequest{View on GitHub (pinned to 482b49bf1a)
Solutions
- Convert to a syscall.Signal before calling: executor.Signal(syscall.SIGTERM) instead of passing a custom os.Signal
- Map named signals from task config (e.g. "SIGINT") to syscall.Signal values via syscall.Signals parsing
- Reject or translate unsupported signals at the driver layer before invoking Signal
- Check the value at runtime with a type assertion and handle unsupported signals explicitly
Example fix
// before
var sig os.Signal = myCustomSignal{}
executor.Signal(sig)
// after
if s, ok := mySignal.(syscall.Signal); ok {
executor.Signal(s)
} else {
executor.Signal(syscall.SIGTERM)
} Defensive patterns
Strategy: type-guard
Validate before calling
if _, ok := sig.(syscall.Signal); !ok { sig = syscall.SIGTERM } Type guard
func isSyscallSignal(s os.Signal) (syscall.Signal, bool) {
sig, ok := s.(syscall.Signal)
return sig, ok
} Try / catch
if err := executor.Signal(sig); err != nil && strings.Contains(err.Error(), "unsupported signal type") {
err = executor.Signal(syscall.SIGTERM)
} Prevention
- Only pass syscall.SIG* constants to executor.Signal
- Parse task-config signal names into syscall.Signal early
- Validate signal values at driver config load time
When it happens
Trigger: Calling executor.Signal() with a custom signal type, or with values like os.Interrupt wrapped in a non-syscall.Signal implementation of os.Signal.
Common situations: Driver/plugin authors forwarding user-specified signals from task config; using os.Interrupt/os.Kill constants in code paths expecting syscall.SIGTERM-style values; Go code compiling where os.Signal is satisfied by non-numeric signal types.
Related errors
- CSI Plugin loaded incorrectly
- nil response from plugin.NodeExpandVolume
- Task not found
- Failed to signal task: %s, err: %v
- CSI plugin failed to register: %w
AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04).
Data as JSON: /api/errors/a75aab6377a78b60.
Report an issue: GitHub.