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

  1. Reuse the single subscription and multiplex event types through the one notification channel on the client side.
  2. Expose separate subscribe methods (e.g. subscribeA, subscribeB), each getting its own Notifier and subscription.
  3. 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

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


AI-assisted analysis of ethereum/go-ethereum@6bb0588ad8 (2026-08-15). Data as JSON: /api/errors/c2f70b92ecd2a199. Report an issue: GitHub.