ethereum/go-ethereum · error
channel given to Subscribe must not be nil
Error message
channel given to Subscribe must not be nil
What it means
rpc.Client.Subscribe panics when the channel argument is nil. Subscribe uses reflection to verify the argument is a writable channel before registering the subscription; a nil channel cannot receive notifications, so the library treats it as a programming error and panics immediately rather than failing at runtime later.
Source
Thrown at rpc/client.go:511
// registering a subscription. Server notifications for the subscription are
// sent to the given channel. The element type of the channel must match the
// expected type of content returned by the subscription.
//
// The context argument cancels the RPC request that sets up the subscription but has no
// effect on the subscription after Subscribe has returned.
//
// Slow subscribers will be dropped eventually. Client buffers up to 20000 notifications
// before considering the subscriber dead. The subscription Err channel will receive
// ErrSubscriptionQueueOverflow. Use a sufficiently large buffer on the channel or ensure
// that the channel usually has at least one reader to prevent this issue.
func (c *Client) Subscribe(ctx context.Context, namespace string, channel interface{}, args ...interface{}) (*ClientSubscription, error) {
// Check type of channel first.
chanVal := reflect.ValueOf(channel)
if chanVal.Kind() != reflect.Chan || chanVal.Type().ChanDir()&reflect.SendDir == 0 {
panic(fmt.Sprintf("channel argument of Subscribe has type %T, need writable channel", channel))
}
if chanVal.IsNil() {
panic("channel given to Subscribe must not be nil")
}
if c.isHTTP {
return nil, ErrNotificationsUnsupported
}
msg, err := c.newMessage(namespace+subscribeMethodSuffix, args...)
if err != nil {
return nil, err
}
op := &requestOp{
ids: []json.RawMessage{msg.ID},
resp: make(chan []*jsonrpcMessage, 1),
sub: newClientSubscription(c, namespace, chanVal),
}
// Send the subscription request.
// The arrival and validity of the response is signaled on sub.quit.
if err := c.send(ctx, op, msg); err != nil {View on GitHub (pinned to 6bb0588ad8)
Solutions
- Initialize the channel before subscribing: ch := make(chan Type, 128), then pass ch.
- Ensure the variable passed is not shadowed or nil at the call site (log %T and nil-ness with reflect before the call).
- Confirm the connection is a WebSocket/IPC connection, since HTTP clients return ErrNotificationsUnsupported instead of working.
- Buffer the channel (the docs suggest a large buffer or a permanently reading goroutine) to avoid ErrSubscriptionQueueOverflow later.
Example fix
// before var headers chan types.Header sub, err := client.Subscribe(ctx, "eth", headers, "newHeads") // after headers := make(chan types.Header, 128) sub, err := client.Subscribe(ctx, "eth", headers, "newHeads")
Defensive patterns
Strategy: validation
Validate before calling
func checkChannel(ch interface{}) error {
v := reflect.ValueOf(ch)
if v.Kind() != reflect.Chan || v.Type().ChanDir()&reflect.SendDir == 0 {
return fmt.Errorf("%T is not a writable channel", ch)
}
if v.IsNil() {
return errors.New("channel is nil")
}
return nil
}
if err := checkChannel(headers); err != nil {
return err
}
sub, err := client.Subscribe(ctx, "eth", headers, "newHeads") Prevention
- Always create the channel with make(chan T, n) in the same expression or block that passes it to Subscribe.
- Lint for nil channel variables: initialize at declaration, never var ch chan T alone.
- Confirm the connection is ws:// or ipc:// before subscribing; http:// clients never support subscriptions.
When it happens
Trigger: Calling client.Subscribe(ctx, "eth", nil, ...) or passing a channel variable that was declared but never initialized (var ch chan int). A separate panic in the same function fires for non-channel types or receive-only channels; this one fires only when the value is a writable channel value that is nil.
Common situations: Declaring var notifications chan types.Header instead of make(chan types.Header, N); passing a nil interface holding a nil channel; refactoring code that previously used a pointer-to-channel. Also note Subscribe returns ErrNotificationsUnsupported over HTTP regardless of the channel.
Related errors
- can't create multiple subscriptions with Notifier
- can't create subscription after subscribe call has returned
- can't Notify before subscription is created
- Notify with wrong ID
- nil TextMapPropagator configured
AI-assisted analysis of ethereum/go-ethereum@6bb0588ad8 (2026-08-15).
Data as JSON: /api/errors/8cb1ac4d08df91f4.
Report an issue: GitHub.