{"record":{"id":"a75aab6377a78b60","repo":"hashicorp/nomad","slug":"unsupported-signal-type-q","errorCode":null,"errorMessage":"unsupported signal type: %q","messagePattern":"unsupported signal type: %q","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"drivers/shared/executor/grpc_client.go","lineNumber":172,"sourceCode":"\t\tstats, err := drivers.TaskStatsFromProto(resp.Stats)\n\t\tif err != nil {\n\t\t\tc.logger.Error(\"failed to decode stats from RPC\", \"error\", err, \"stats\", resp.Stats)\n\t\t\tcontinue\n\t\t}\n\n\t\tselect {\n\t\tcase ch <- stats:\n\t\tcase <-ctx.Done():\n\t\t\treturn\n\t\t}\n\t}\n}\n\nfunc (c *grpcExecutorClient) Signal(s os.Signal) error {\n\tctx := context.Background()\n\tsig, ok := s.(syscall.Signal)\n\tif !ok {\n\t\treturn fmt.Errorf(\"unsupported signal type: %q\", s.String())\n\t}\n\treq := &proto.SignalRequest{\n\t\tSignal: int32(sig),\n\t}\n\tif _, err := c.client.Signal(ctx, req); err != nil {\n\t\treturn err\n\t}\n\n\treturn nil\n}\n\nfunc (c *grpcExecutorClient) Exec(deadline time.Time, cmd string, args []string) ([]byte, int, error) {\n\tctx := context.Background()\n\tpbDeadline, err := ptypes.TimestampProto(deadline)\n\tif err != nil {\n\t\treturn nil, 0, err\n\t}\n\treq := &proto.ExecRequest{","sourceCodeStart":154,"sourceCodeEnd":190,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/drivers/shared/executor/grpc_client.go#L154-L190","documentation":"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.","triggerScenarios":"Calling executor.Signal() with a custom signal type, or with values like os.Interrupt wrapped in a non-syscall.Signal implementation of os.Signal.","commonSituations":"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.","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"],"exampleFix":"// before\nvar sig os.Signal = myCustomSignal{}\nexecutor.Signal(sig)\n// after\nif s, ok := mySignal.(syscall.Signal); ok {\n    executor.Signal(s)\n} else {\n    executor.Signal(syscall.SIGTERM)\n}","handlingStrategy":"type-guard","validationCode":"if _, ok := sig.(syscall.Signal); !ok { sig = syscall.SIGTERM }","typeGuard":"func isSyscallSignal(s os.Signal) (syscall.Signal, bool) {\n    sig, ok := s.(syscall.Signal)\n    return sig, ok\n}","tryCatchPattern":"if err := executor.Signal(sig); err != nil && strings.Contains(err.Error(), \"unsupported signal type\") {\n    err = executor.Signal(syscall.SIGTERM)\n}","preventionTips":["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"],"tags":["signal","grpc","type-assertion"],"backgroundTag":"unsupported-signal-type","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"}