docker/cli · error

cannot attach to a restarting container, wait until it is…

Error message

cannot attach to a restarting container, wait until it is running

What it means

inspectContainerAndCheckState returns errors.New("cannot attach to a restarting container, wait until it is running") at line 37 when c.Container.State.Restarting is true. During a restart policy triggered cycle the container is transitional (not yet Running), so attach is rejected; the caller should wait for the container to reach a stable running state.

Solutions

  1. Wait for the container to reach Running: `docker wait` is not suitable here; poll `docker inspect -f '{{.State.Running}}' <id>` until true, or use `until docker inspect -f '{{.State.Status}}' id | grep -q running; do ...`.
  2. If it crash-loops, inspect `docker logs <id>` and fix the crash cause (entrypoint, missing config).
  3. Temporarily remove/loosen the restart policy to inspect, or `docker update --restart=no <id>`.

Example fix

# before (container mid-restart)
docker attach web
# after — wait for running then attach
until [ "$(docker inspect -f '{{.State.Running}}' web)" = "true" ]; do sleep 1; done
docker attach web
Defensive patterns

Strategy: validation

Validate before calling

c, err := cli.Client().ContainerInspect(ctx, id, client.ContainerInspectOptions{})
if err != nil { return err }
if c.State.Restarting {
    // wait for Running: poll or back off
    return fmt.Errorf("container %s is restarting; retry shortly", id)
}

Try / catch

for attempt := 0; attempt < maxRetry; attempt++ {
    if _, err := inspectContainerAndCheckState(ctx, cli.Client(), id); err == nil { break }
    if !strings.Contains(err.Error(), "restarting container") { return err }
    // brief wait, then retry (use a timer, not a busy loop)
}

Prevention

When it happens

Trigger: Running `docker attach <id>` against a container with a restart policy (e.g. --restart=always/unless-stopped/on-failure) that is currently mid-restart — the process exited and the daemon is restarting it.

Common situations: Containers that crash-loop with a restart policy; attaching immediately after a host/daemon restart; flapping services; attaching during a restart-policy backoff window.

Related errors


AI-assisted analysis of docker/cli@4f84911bfe (2026-08-07). Data as JSON: /api/errors/d35c1cf1e7f2bb8d. Report an issue: GitHub.

Appendix: source

Thrown at cli/command/container/attach.go:37

type AttachOptions struct {
	NoStdin    bool
	Proxy      bool
	DetachKeys string
}

func inspectContainerAndCheckState(ctx context.Context, apiClient client.APIClient, args string) (*container.InspectResponse, error) {
	c, err := apiClient.ContainerInspect(ctx, args, client.ContainerInspectOptions{})
	if err != nil {
		return nil, err
	}
	if !c.Container.State.Running {
		return nil, errors.New("cannot attach to a stopped container, start it first")
	}
	if c.Container.State.Paused {
		return nil, errors.New("cannot attach to a paused container, unpause it first")
	}
	if c.Container.State.Restarting {
		return nil, errors.New("cannot attach to a restarting container, wait until it is running")
	}

	return &c.Container, nil
}

// newAttachCommand creates a new cobra.Command for `docker attach`
func newAttachCommand(dockerCLI command.Cli) *cobra.Command {
	var opts AttachOptions

	cmd := &cobra.Command{
		Use:   "attach [OPTIONS] CONTAINER",
		Short: "Attach local standard input, output, and error streams to a running container",
		Args:  cli.ExactArgs(1),
		RunE: func(cmd *cobra.Command, args []string) error {
			containerID := args[0]
			return RunAttach(cmd.Context(), dockerCLI, containerID, &opts)
		},
		Annotations: map[string]string{

View on GitHub (pinned to 4f84911bfe)