ipfs/kubo · warning
%s close: %w
Error message
%s close: %w
What it means
CloseWithCtx runs a subsystem's Close in a goroutine and waits up to the caller's context deadline; if the subsystem does not finish closing in time, it logs and returns '<name> close: <ctx.Err()>' (usually context.DeadlineExceeded). The subsystem may still be closing in the background.
Source
Thrown at core/shutdown/close.go:29
var closeLog = logging.Logger("shutdown")
// CloseWithCtx runs close in a goroutine and returns when it finishes or
// when ctx is done, whichever comes first. If ctx fires before close
// returns, the goroutine is leaked intentionally; the process is about to
// exit, so the leak is bounded by process lifetime. Logs at ERROR which
// subsystem failed to close in time so operators see it in journal/docker
// logs.
func CloseWithCtx(ctx context.Context, name string, close func() error) error {
done := make(chan error, 1)
start := time.Now()
go func() { done <- close() }()
select {
case err := <-done:
return err
case <-ctx.Done():
closeLog.Errorf("subsystem %q failed to close within shutdown deadline (after %s): %s",
name, time.Since(start), ctx.Err())
return fmt.Errorf("%s close: %w", name, ctx.Err())
}
}
View on GitHub (pinned to 329838acdf)
Solutions
- Increase the shutdown deadline context (e.g. 30s) given to CloseWithCtx
- Check shutdown logs for the named subsystem to find what is blocking its Close
- Ensure the subsystem's dependencies are closed in correct order (children before parents)
- Gracefully stop active operations (downloads, GC, FUSE unmounts) before shutdown
Example fix
// before closeCtx, cancel := context.WithTimeout(ctx, time.Second) // after closeCtx, cancel := context.WithTimeout(ctx, 30*time.Second)
Defensive patterns
Strategy: try-catch
Validate before calling
// nothing to validate beforehand; ensure subsystems are idle before closing
if node.IsBusy() { time.Sleep(...) } Try / catch
closeCtx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
if err := CloseWithCtx(closeCtx, node, "node"); err != nil {
if errors.Is(err, context.DeadlineExceeded) {
log.Warn("node close exceeded deadline; may still be flushing")
}
} Prevention
- Give shutdown a generous deadline proportional to datastore size
- Stop active operations (GC, pins, FUSE) before closing
- Check shutdown logs for the subsystem named in the error
When it happens
Trigger: Calling CloseWithCtx with a too-short context while a subsystem (e.g. datastore, blockservice, libp2p host) hangs in Close — open handles, slow flushes, stuck network calls.
Common situations: Daemon shutdown timing out because a FUSE mount or datastore flush blocks; tests or scripts using a 1-2 second shutdown timeout on a node with large datastore GC.
Related errors
AI-assisted analysis of ipfs/kubo@329838acdf (2026-09-03).
Data as JSON: /api/errors/45b73b08ff220da8.
Report an issue: GitHub.