docker/cli · error

cannot attach to a paused container, unpause it first

Error message

cannot attach to a paused container, unpause it first

What it means

inspectContainerAndCheckState returns errors.New("cannot attach to a paused container, unpause it first") at line 34 when c.Container.State.Paused is true. A paused container has its processes frozen (cgroup freezer), so its I/O streams are not advancing and attach would hang; the CLI requires the container to be unpaused (Running and not Paused) first.

Solutions

  1. Unpause first: `docker unpause <id>` then `docker attach <id>`.
  2. Confirm state with `docker ps`/`docker inspect` and look for Status 'Up (Paused)'.
  3. Avoid pausing containers you intend to interact with via attach.

Example fix

# before (container is paused)
docker attach web
# after
docker unpause web && 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.Paused {
    // unpause before attach
    _ = cli.Client().ContainerUnpause(ctx, id, client.ContainerUnpauseOptions{})
}

Try / catch

if _, err := inspectContainerAndCheckState(ctx, cli.Client(), id); err != nil {
    if strings.Contains(err.Error(), "paused container") {
        _ = cli.Client().ContainerUnpause(ctx, id, client.ContainerUnpauseOptions{})
        // retry attach
    }
    return err
}

Prevention

When it happens

Trigger: Running `docker attach <id>` against a container previously paused via `docker pause <id>`, while it remains in the 'Paused' state.

Common situations: Pausing a container for debugging/snapshot then forgetting to unpause; automation that pauses before attach; pausing to inspect a memory dump.

Related errors


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

Appendix: source

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

)

// AttachOptions group options for `attach` command
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]

View on GitHub (pinned to 4f84911bfe)