{"record":{"id":"bb9e5fc3c6347f98","repo":"vxcontrol/pentagi","slug":"container-shutdown-failed-w","errorCode":null,"errorMessage":"container shutdown failed: %w","messagePattern":"container shutdown failed: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"backend/pkg/docker/client.go","lineNumber":734,"sourceCode":"\t_, err := dc.client.ContainerRemove(ctx, containerID, client.ContainerRemoveOptions{\n\t\tRemoveVolumes: true,\n\t\tForce:         true,\n\t})\n\tif err != nil && !cerrdefs.IsNotFound(err) {\n\t\tlogger.WithError(err).Error(\"failed to remove the container that did not start\")\n\t}\n}\n\nfunc (dc *dockerClient) StopContainer(ctx context.Context, containerID string, dbID int64) error {\n\tlogger := dc.logger.WithContext(ctx).WithField(\"local_id\", containerID)\n\tlogger.Info(\"initiating container shutdown sequence\")\n\n\t_, stopErr := dc.client.ContainerStop(ctx, containerID, client.ContainerStopOptions{})\n\tif stopErr != nil {\n\t\tif cerrdefs.IsNotFound(stopErr) {\n\t\t\tlogger.Warn(\"target container already removed or never existed\")\n\t\t} else {\n\t\t\treturn fmt.Errorf(\"container shutdown failed: %w\", stopErr)\n\t\t}\n\t}\n\n\t_, err := dc.db.UpdateContainerStatus(ctx, database.UpdateContainerStatusParams{\n\t\tStatus: database.ContainerStatusStopped,\n\t\tID:     dbID,\n\t})\n\tif err != nil {\n\t\treturn fmt.Errorf(\"database status update failed during container stop: %w\", err)\n\t}\n\n\tlogger.Info(\"container shutdown completed successfully\")\n\n\treturn nil\n}\n\nfunc (dc *dockerClient) RemoveContainer(ctx context.Context, containerID string, dbID int64) error {\n\tlogger := dc.logger.WithContext(ctx).WithField(\"local_id\", containerID)","sourceCodeStart":716,"sourceCodeEnd":752,"githubUrl":"https://github.com/vxcontrol/pentagi/blob/ea665308baaff015b226f308438a68d929d0f29b/backend/pkg/docker/client.go#L716-L752","documentation":"StopContainer wraps any error from the Docker daemon's ContainerStop call that is not a 'not found'. It means the daemon accepted the request but failed to stop the container (or the connection to the daemon failed).","triggerScenarios":"dc.client.ContainerStop returns a non-NotFound error: daemon unreachable mid-request, container in a state that cannot stop (paused, dead), timeout exceeded while graceful stop fails, or an API/network error between the client and dockerd.","commonSituations":"Docker daemon restarting or being upgraded while flows are torn down; container paused via `docker pause`; container already in 'dead' state; transient network failure to the Docker socket or TCP endpoint; cgroup/driver issues on the host preventing SIGKILL delivery.","solutions":["Verify the container state with `docker inspect -f '{{.State.Status}}' <id>` and unpause or force-kill manually if paused/dead","Check the Docker daemon is healthy (`docker info`) and reachable from the PentAGI backend","Retry StopContainer / fall through to RemoveContainer with Force:true, which force-kills the container","Inspect dockerd logs (`journalctl -u docker`) for the underlying stop failure"],"exampleFix":"// before\n_, stopErr := dc.client.ContainerStop(ctx, containerID, client.ContainerStopOptions{})\n// after\n_, stopErr := dc.client.ContainerStop(ctx, containerID, client.ContainerStopOptions{Timeout: &shortTimeout})\nif stopErr != nil && !cerrdefs.IsNotFound(stopErr) {\n    logger.WithError(stopErr).Warn(\"graceful stop failed, forcing kill\")\n    _ = dc.client.ContainerKill(ctx, containerID, \"SIGKILL\")\n}","handlingStrategy":"retry","validationCode":"// check daemon and container state before stopping\nstate, err := dockerCli.ContainerInspect(ctx, id)\nif err == nil && state.Container.State != nil && state.Container.State.Paused {\n    dockerCli.ContainerUnpause(ctx, id)\n}","typeGuard":"func isNotFound(err error) bool { return cerrdefs.IsNotFound(err) }","tryCatchPattern":"if err := dc.StopContainer(ctx, id, dbID); err != nil {\n    if !cerrdefs.IsNotFound(err) {\n        log.WithError(err).Warn(\"stop failed; forcing remove\")\n        _ = dc.RemoveContainer(ctx, id, dbID) // Force:true path\n    }\n}","preventionTips":["Keep containers unpaused before teardown","Ensure the Docker daemon is healthy and reachable from the backend","Set a bounded stop timeout so graceful stop falls through to kill","Monitor dockerd restarts and retry teardown failures"],"tags":["docker","container-lifecycle","go"],"backgroundTag":"docker-container-stop-failed","analyzedSha":"ea665308baaff015b226f308438a68d929d0f29b","analyzedAt":"2026-09-01T14:16:31.421Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}