ethereum/go-ethereum · error
can't create multiple subscriptions with Notifier
Error message
can't create multiple subscriptions with Notifier
What it means
A rpc.Notifier can create only one subscription per RPC method call. CreateSubscription panics if a subscription already exists for this Notifier, because the notification routing machinery (n.sub, activation, buffering) is single-subscription by design.
Source
Thrown at rpc/subscription.go:122
namespace string
mu sync.Mutex
sub *Subscription
buffer []any
callReturned bool
activated bool
}
// CreateSubscription returns a new subscription that is coupled to the
// RPC connection. By default subscriptions are inactive and notifications
// are dropped until the subscription is marked as active. This is done
// by the RPC server after the subscription ID is send to the client.
func (n *Notifier) CreateSubscription() *Subscription {
n.mu.Lock()
defer n.mu.Unlock()
if n.sub != nil {
panic("can't create multiple subscriptions with Notifier")
} else if n.callReturned {
panic("can't create subscription after subscribe call has returned")
}
n.sub = &Subscription{ID: n.h.idgen(), namespace: n.namespace, err: make(chan error, 1)}
return n.sub
}
// Notify sends a notification to the client with the given data as payload.
// If an error occurs the RPC connection is closed and the error is returned.
func (n *Notifier) Notify(id ID, data any) error {
n.mu.Lock()
defer n.mu.Unlock()
if n.sub == nil {
panic("can't Notify before subscription is created")
} else if n.sub.ID != id {
panic("Notify with wrong ID")
}View on GitHub (pinned to 6bb0588ad8)
Solutions
- Reuse the single subscription and multiplex event types through the one notification channel on the client side.
- Expose separate subscribe methods (e.g. subscribeA, subscribeB), each getting its own Notifier and subscription.
- Review the service method to ensure CreateSubscription is called exactly once per incoming subscribe request.
Example fix
// before sub1 := notifier.CreateSubscription() sub2 := notifier.CreateSubscription() // panic // after sub := notifier.CreateSubscription() // send all event kinds over sub; clients discriminate by payload type
Defensive patterns
Strategy: validation
Validate before calling
// Inside an RPC service method:
notifier, enabled := api.Notifier(ctx)
if !enabled {
return nil, errors.New("subscriptions not supported")
}
if sub := notifier.(*rpc.Notifier); sub != nil {
// create exactly one subscription per method call
s := notifier.CreateSubscription()
_ = s
} Prevention
- Call CreateSubscription exactly once per subscribe method, at a fixed code location.
- Design multi-event APIs as multiple subscribe methods rather than multiple subscriptions per call.
- Add a code review checklist item: 'one CreateSubscription per Notifier'.
When it happens
Trigger: In an RPC service method that already obtained notifier, _ := api.Notifier(...) and created a subscription, calling notifier.CreateSubscription() a second time within the same call.
Common situations: Copy-pasting a subscribe handler that creates a subscription inside a loop; refactoring a service method to return multiple event streams; a subscribe method that handles several event types by creating one subscription per type.
Related errors
- can't create subscription after subscribe call has returned
- can't Notify before subscription is created
- Notify with wrong ID
- channel given to Subscribe must not be nil
- channel argument of Subscribe has type %T, need writable cha
AI-assisted analysis of ethereum/go-ethereum@6bb0588ad8 (2026-08-15).
Data as JSON: /api/errors/c2f70b92ecd2a199.
Report an issue: GitHub.