{"record":{"id":"c2a5bcffd505a5f3","repo":"GoogleContainerTools/skaffold","slug":"pruning-removed-container-w","errorCode":null,"errorMessage":"pruning removed container: %w","messagePattern":"pruning removed container: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/skaffold/docker/image.go","lineNumber":223,"sourceCode":"\t}\n}\n\nfunc (l *localDaemon) ContainerExists(ctx context.Context, name string) bool {\n\t_, err := l.apiClient.ContainerInspect(ctx, name, client.ContainerInspectOptions{})\n\treturn err == nil\n}\n\n// Delete stops, removes, and prunes a running container\nfunc (l *localDaemon) Delete(ctx context.Context, out io.Writer, id string) error {\n\tif _, err := l.apiClient.ContainerStop(ctx, id, client.ContainerStopOptions{}); err != nil {\n\t\tlog.Entry(ctx).Debugf(\"unable to stop running container: %s\", err.Error())\n\t}\n\tif _, err := l.apiClient.ContainerRemove(ctx, id, client.ContainerRemoveOptions{}); err != nil {\n\t\tlog.Entry(ctx).Warnf(\"unable to remove container: %s\", err.Error())\n\t}\n\t_, err := l.apiClient.ContainerPrune(ctx, client.ContainerPruneOptions{})\n\tif err != nil {\n\t\treturn fmt.Errorf(\"pruning removed container: %w\", err)\n\t}\n\treturn nil\n}\n\n// Run creates a container from a given image reference, and returns a wait channel and the container ID.\nfunc (l *localDaemon) Run(ctx context.Context, out io.Writer, opts ContainerCreateOpts) (<-chan container.WaitResponse, <-chan error, string, error) {\n\tif opts.ContainerConfig == nil {\n\t\treturn nil, nil, \"\", fmt.Errorf(\"cannot call Run with empty container config\")\n\t}\n\tc, err := l.apiClient.ContainerCreate(ctx, client.ContainerCreateOptions{\n\t\tConfig: opts.ContainerConfig,\n\t\tHostConfig: &container.HostConfig{\n\t\t\tNetworkMode:  container.NetworkMode(opts.Network),\n\t\t\tVolumesFrom:  opts.VolumesFrom,\n\t\t\tPortBindings: opts.Bindings,\n\t\t\tMounts:       opts.Mounts,\n\t\t},\n\t\tName: opts.Name,","sourceCodeStart":205,"sourceCodeEnd":241,"githubUrl":"https://github.com/GoogleContainerTools/skaffold/blob/a1189de023efc32d4b8e11f395acc678aa555011/pkg/skaffold/docker/image.go#L205-L241","documentation":"localDaemon.Delete removes a container and then prunes to clean up, returning \"pruning removed container: %w\" if apiClient.ContainerPrune fails. Note the container removal itself only logs a warning; it is the prune step that surfaces as a hard error. This wraps daemon/transport failures during the prune API call.","triggerScenarios":"Calling Delete(ctx, id) (the LocalDaemon interface method) when ContainerPrune returns an error: Docker daemon stopped/restarting mid-call, context cancelled or timed out, daemon returned 500, or network connection to a remote DOCKER_HOST dropped during the prune request.","commonSituations":"Skaffold dev cleanup while Docker Desktop is restarting; long-running prune hitting the daemon's request timeout; remote Docker (ssh/tcp DOCKER_HOST) connection reset; daemon disk pressure causing prune API failure.","solutions":["Verify the daemon is healthy with `docker info`; restart Docker Desktop/daemon if it is wedged, then retry the delete.","Check the context/deadline: rerun without cancellation or increase timeout if the prune timed out.","For remote DOCKER_HOST, confirm connectivity (ssh tunnel / tcp port) and retry.","Treat as cleanup-best-effort: confirm the container itself is gone (`docker ps -a`); the prune failure usually only affects reclaiming stopped containers/networks."],"exampleFix":"// before: delete fails at prune when daemon is restarting\nif _, err := l.apiClient.ContainerPrune(ctx, client.ContainerPruneOptions{}); err != nil {\n    return fmt.Errorf(\"pruning removed container: %w\", err)\n}\n\n// after (caller-side resilience): log prune failure instead of failing cleanup\nif _, err := l.apiClient.ContainerPrune(ctx, client.ContainerPruneOptions{}); err != nil {\n    log.Entry(ctx).Warnf(\"unable to prune after container removal: %s\", err.Error())\n}\nreturn nil","handlingStrategy":"try-catch","validationCode":"// Go: check daemon reachability before Delete cleanup\ncli, _ := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation())\nif _, err := cli.Ping(context.Background()); err != nil {\n    log.Warnf(\"docker daemon unreachable, skipping container cleanup: %v\", err)\n    return nil\n}","typeGuard":null,"tryCatchPattern":"if err := daemon.Delete(ctx, id); err != nil {\n    // cleanup is best-effort: the container may already be removed\n    if strings.Contains(err.Error(), \"pruning removed container\") {\n        log.Warnf(\"post-removal prune failed (container itself likely gone): %v\", err)\n        return nil\n    }\n    return err\n}","preventionTips":["Avoid restarting Docker Desktop while skaffold dev is running; stop the session first.","Increase client timeouts for remote DOCKER_HOST connections.","Treat delete/prune errors as warnings in teardown paths.","Monitor daemon health (`docker info`) before long dev sessions."],"tags":["docker","daemon","cleanup","prune"],"backgroundTag":"docker-daemon-unreachable","analyzedSha":"a1189de023efc32d4b8e11f395acc678aa555011","analyzedAt":"2026-09-05T12:09:27.064Z","contentChangedAt":"2026-09-05T12:09:27.064Z","schemaVersion":2},"datasetVersion":"2026-09-12T17:17:11.597Z"}