jesseduffield/lazydocker · error

Container does not support attaching. You must either run th

Error message

Container does not support attaching. You must either run the service with the '-it' flag or use `stdin_open: true, tty: true` in the docker-compose.yml file

What it means

Thrown by Container.Attach() when the container's inspect payload shows Config.OpenStdin == false. 'docker attach' only makes sense for containers started with an interactive stdin, so lazydocker refuses to attach to containers created without -it (or stdin_open: true, tty: true in compose). The message itself tells you the two supported remedies.

Source

Thrown at pkg/commands/container.go:98

	c.Log.Warn(fmt.Sprintf("unpausing container %s", c.Name))
	return c.Client.ContainerUnpause(context.Background(), c.ID)
}

// Restart restarts the container
func (c *Container) Restart() error {
	c.Log.Warn(fmt.Sprintf("restarting container %s", c.Name))
	return c.Client.ContainerRestart(context.Background(), c.ID, container.StopOptions{})
}

// Attach attaches the container
func (c *Container) Attach() (*exec.Cmd, error) {
	if !c.DetailsLoaded() {
		return nil, errors.New(c.Tr.WaitingForContainerInfo)
	}

	// verify that we can in fact attach to this container
	if !c.Details.Config.OpenStdin {
		return nil, errors.New(c.Tr.UnattachableContainerError)
	}

	if c.Container.State == "exited" {
		return nil, errors.New(c.Tr.CannotAttachStoppedContainerError)
	}

	c.Log.Warn(fmt.Sprintf("attaching to container %s", c.Name))
	// TODO: use SDK
	cmd := c.OSCommand.NewCmd("docker", "attach", "--sig-proxy=false", c.ID)
	return cmd, nil
}

// Top returns process information
func (c *Container) Top(ctx context.Context) (container.TopResponse, error) {
	detail, err := c.Inspect()
	if err != nil {
		return container.TopResponse{}, err
	}

View on GitHub (pinned to 7e7aadc207)

Solutions

  1. Recreate the container with an interactive TTY: `docker run -it ...` or add `stdin_open: true` and `tty: true` to the service in docker-compose.yml.
  2. If you only need a shell, use exec instead: `docker exec -it <container> sh` (in lazydocker this is the 'E' key), which does not require OpenStdin.
  3. For compose services: `docker compose up -d --force-recreate <service>` after editing the yaml so the new flags take effect.

Example fix

# before (docker-compose.yml)
services:
  app:
    image: myapp

# after (docker-compose.yml)
services:
  app:
    image: myapp
    stdin_open: true
    tty: true
Defensive patterns

Strategy: validation

Validate before calling

detail, err := container.Inspect()
if err != nil {
    return err
}
if !detail.Config.OpenStdin {
    // show guidance instead of attempting attach
    return showHint("recreate with -it or stdin_open+tty in compose")
}

Try / catch

if _, err := container.Attach(); err != nil {
    if strings.Contains(err.Error(), "-it") { // UnattachableContainerError
        suggestExecInstead(container)
    }
}

Prevention

When it happens

Trigger: Calling Container.Attach() on a container created with `docker run` without -i/-t flags, or on a compose service whose yaml lacks `stdin_open: true` and `tty: true`, after details have loaded and OpenStdin is false.

Common situations: Background services (databases, web servers) defined in docker-compose.yml with no tty/stdin_open; containers started by CI or orchestration tools that never allocate stdin; long-running daemon containers where attach is the wrong tool and `docker exec -it ... sh` is what the user actually wants.

Related errors


AI-assisted analysis of jesseduffield/lazydocker@7e7aadc207 (2026-08-15). Data as JSON: /api/errors/ef532d5833cba960. Report an issue: GitHub.