{"record":{"id":"38a04f24cf8c2219","repo":"containerd/containerd","slug":"failed-to-stop-stream-server-w","errorCode":null,"errorMessage":"failed to stop stream server: %w","messagePattern":"failed to stop stream server: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"internal/cri/server/service.go","lineNumber":415,"sourceCode":"\t}\n\treturn nil\n}\n\n// Close stops the CRI service.\n// TODO(random-liu): Make close synchronous.\nfunc (c *criService) Close() error {\n\tlog.L.Info(\"Stop CRI service\")\n\tfor name, h := range c.cniNetConfMonitor {\n\t\tif err := h.stop(); err != nil {\n\t\t\tlog.L.WithError(err).Errorf(\"failed to stop cni network conf monitor for %s\", name)\n\t\t}\n\t}\n\tc.eventMonitor.Stop()\n\tif c.statsCollector != nil {\n\t\tc.statsCollector.Stop()\n\t}\n\tif err := c.streamServer.Stop(); err != nil {\n\t\treturn fmt.Errorf(\"failed to stop stream server: %w\", err)\n\t}\n\treturn nil\n}\n\n// IsInitialized indicates whether CRI service has finished initialization.\nfunc (c *criService) IsInitialized() bool {\n\treturn c.initialized.Load()\n}\n\nfunc (c *criService) introspectRuntimeHandler(ctx context.Context, intro introspection.Service, name string, r criconfig.Runtime) error {\n\th := &runtime.RuntimeHandler{\n\t\tName: name,\n\t}\n\trawFeatures, err := introspectRuntimeFeatures(ctx, intro, r)\n\tif err != nil {\n\t\tlog.G(ctx).WithError(err).Debugf(\"failed to introspect features of runtime %q\", name)\n\t} else {\n\t\th.Features = &runtime.RuntimeHandlerFeatures{}","sourceCodeStart":397,"sourceCodeEnd":433,"githubUrl":"https://github.com/containerd/containerd/blob/4246446a2bf7d03837b0244118d858799393bd80/internal/cri/server/service.go#L397-L433","documentation":"Returned by criService.Close when the CRI streaming server (exec stream exec/serve endpoints) fails to shut down cleanly. Close stops the event monitor and stats collector first, then stops the stream server; any error from streamServer.Stop() is wrapped with %w so the underlying cause (listener close failure, drain timeout) is preserved. It aborts the remainder of shutdown, so callers like Run report shutdown failure even though monitoring already stopped.","triggerScenarios":"Calling Close() (via Run's defer during containerd shutdown or explicit Stop) when the stream server's underlying listener cannot be closed or its Serve goroutine returns an error (port already released unexpectedly, blocked connections, or a custom StreamServer whose Stop returns non-nil).","commonSituations":"containerd daemon shutdown/restart with active exec/attach/port-forward streams; CI teardown races where streams are still being drained; custom streamer implementations returning errors from Stop; port conflicts after rapid restart of containerd.","solutions":["Inspect the wrapped cause (%w) to see why the stream server stop failed — usually a listener close error or drain timeout.","Ensure all active exec/attach streams are terminated or given time to drain before shutting down containerd.","If restarting containerd rapidly, verify the stream port (if configured) is released; adjust stream_server_address/port config.","If it happens at process exit, treat it as non-fatal: containerd is exiting anyway; check for leaked goroutines in custom stream servers.","Update containerd — several stream-server shutdown race fixes landed in later releases."],"exampleFix":"// before: ignoring graceful drain on shutdown\nctr, _ := NewCRIService(...)\nctr.Close()\n// after: stop streaming workloads first, then close\ncancelStreams() // terminate active exec/attach sessions\nctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)\ndefer cancel()\n<-streamsDrained(ctx)\nif err := ctr.Close(); err != nil {\n    log.Warnf(\"cri shutdown: %v\", err)\n}","handlingStrategy":"try-catch","validationCode":"// No pre-call check; ensure streams are drained before Close\nif numActiveExecStreams() > 0 { waitForStreamsDrain(ctx) }","typeGuard":null,"tryCatchPattern":"// Go: handle wrapped error at shutdown\nif err := criService.Close(); err != nil {\n    log.Warnf(\"CRI close failed: %v\", err) // inspect errors.Unwrap for cause\n}","preventionTips":["Terminate active exec/attach/port-forward streams before shutting down containerd.","Use a timeout around shutdown and log the unwrapped cause.","Avoid custom StreamServer implementations unless Stop is idempotent and error-free.","Keep containerd updated for stream shutdown race fixes."],"tags":["cri","shutdown","streaming","containerd"],"backgroundTag":"graceful-shutdown-error","analyzedSha":"4246446a2bf7d03837b0244118d858799393bd80","analyzedAt":"2026-09-02T00:14:43.053Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-09T06:17:21.866Z"}