containerd/containerd · warning

subscription error: %w

Error message

subscription error: %w

What it means

The events service Subscribe loop received a non-nil error on the broker's error queue (errq) and returns it wrapped as 'subscription error'. It indicates the underlying event broker subscription terminated abnormally, not a client transport problem.

Source

Thrown at plugins/services/events/service.go:114

	}

	return empty, nil
}

func (s *service) Subscribe(req *api.SubscribeRequest, srv api.Events_SubscribeServer) error {
	ctx, cancel := context.WithCancel(srv.Context())
	defer cancel()

	eventq, errq := s.events.Subscribe(ctx, req.Filters...)
	for {
		select {
		case ev := <-eventq:
			if err := srv.Send(toProto(ev)); err != nil {
				return fmt.Errorf("failed sending event to subscriber: %w", err)
			}
		case err := <-errq:
			if err != nil {
				return fmt.Errorf("subscription error: %w", err)
			}

			return nil
		}
	}
}

func toProto(env *events.Envelope) *types.Envelope {
	return &types.Envelope{
		Timestamp: protobuf.ToTimestamp(env.Timestamp),
		Namespace: env.Namespace,
		Topic:     env.Topic,
		Event:     typeurl.MarshalProto(env.Event),
	}
}

func fromProto(env *types.Envelope) *events.Envelope {
	return &events.Envelope{

View on GitHub (pinned to 4246446a2b)

Solutions

  1. Re-subscribe after the daemon/subscription is restored
  2. Check daemon logs for broker shutdown or restart at the same time
  3. Ensure clients reconnect with backoff on subscription loss
  4. If persistent, verify the event exchange plugin is healthy and enabled

Example fix

// before: single subscribe, give up on error
// after: client-side retry loop
for {
    err := subscribeEvents(ctx, client)
    if ctx.Err() != nil { return }
    time.Sleep(time.Second)
}
Defensive patterns

Strategy: retry

Try / catch

err := subscribe(ctx)
if err != nil && strings.Contains(err.Error(), "subscription error") {
    select {
    case <-time.After(backoff):
    case <-ctx.Done():
        return ctx.Err()
    }
    return subscribe(ctx) // re-subscribe
}

Prevention

When it happens

Trigger: The event exchange closes the subscriber's error channel with an error, typically because the subscription's context was canceled or the broker was shut down while the stream was active.

Common situations: containerd daemon shutting down while clients hold event subscriptions; the Subscribe context (client disconnect) canceled the broker subscription; internal broker misuse.

Related errors


AI-assisted analysis of containerd/containerd@4246446a2b (2026-09-02). Data as JSON: /api/errors/cf781ce0bc64ac4b. Report an issue: GitHub.