containerd/containerd · error
errdefs.ErrNotImplemented
errdefs.ErrNotImplemented
Error message
unsupported events client %T: %w
What it means
NewRemoteEvents accepts a GRPC or TTRPC client; any other client type hits the default case and panics with an ErrNotImplemented error. This is a programming/typing mistake: the library only supports *grpc.ClientConn and *ttrpc.Client for remote event proxying.
Source
Thrown at core/events/proxy/remote_events.go:61
switch c := client.(type) {
case api.EventsClient:
return &grpcEventsProxy{
client: c,
}
case api.TTRPCEventsClient:
return &ttrpcEventsProxy{
client: c,
}
case grpc.ClientConnInterface:
return &grpcEventsProxy{
client: api.NewEventsClient(c),
}
case *ttrpc.Client:
return &ttrpcEventsProxy{
client: api.NewTTRPCEventsClient(c),
}
default:
panic(fmt.Errorf("unsupported events client %T: %w", client, errdefs.ErrNotImplemented))
}
}
type grpcEventsProxy struct {
client api.EventsClient
}
func (p *grpcEventsProxy) Publish(ctx context.Context, topic string, event events.Event) error {
evt, err := typeurl.MarshalAny(event)
if err != nil {
return err
}
req := &api.PublishRequest{
Topic: topic,
Event: typeurl.MarshalProto(evt),
}
if _, err := p.client.Publish(ctx, req); err != nil {
return errgrpc.ToNative(err)View on GitHub (pinned to 4246446a2b)
Solutions
- Pass a *grpc.ClientConn or *ttrpc.Client as the client argument
- Type-switch or assert the concrete client type before calling NewRemoteEvents
- Obtain the correct client from the containerd client instance (e.g. client.Conn() for grpc)
Example fix
// before err := remote.NewRemoteEvents(ctx, myWrappedClient, ns) // panics // after conn, _ := myWrappedClient.GRPCConn() err := remote.NewRemoteEvents(ctx, conn, ns)
Defensive patterns
Strategy: type-guard
Validate before calling
switch c := client.(type) {
case *grpc.ClientConn, *ttrpc.Client:
// ok
default:
return fmt.Errorf("unsupported events client %T", client)
} Type guard
func isSupportedEventsClient(client any) bool {
switch client.(type) {
case *grpc.ClientConn, *ttrpc.Client:
return true
}
return false
} Try / catch
func() (err error) {
defer func() { if r := recover(); r != nil { err = fmt.Errorf("NewRemoteEvents: %v", r) } }()
return remote.NewRemoteEvents(ctx, client, ns)
} Prevention
- Only pass raw *grpc.ClientConn or *ttrpc.Client to NewRemoteEvents
- Assert concrete types before calling; NewRemoteEvents panics rather than returning an error
- Recover from panics when calling APIs documented to panic
When it happens
Trigger: Calling events.NewRemoteEvents(ctx, client, ...) with a client other than *grpc.ClientConn or *ttrpc.Client — e.g. passing a wrapped client, an interface value, or nil of the wrong concrete type.
Common situations: Passing a custom dialer's connection wrapper; mixing containerd client internals between ttrpc and grpc; a refactor that changed the client type without updating the call.
Related errors
- errdefs.ErrNotImplemented
- unsupported event
- failed publishing event: %w
- envelope topic %q: %w
- failed parsing subscription filters: %w
AI-assisted analysis of containerd/containerd@4246446a2b (2026-09-02).
Data as JSON: /api/errors/e03fc4f9217176e6.
Report an issue: GitHub.