GoogleContainerTools/skaffold · error

failed to remove old container %s for image %s: %w

Error message

failed to remove old container %s for image %s: %w

What it means

Before deploying a new container for an image, the Docker deployer removes the previous container tracked for that image. If `client.Delete` fails to remove the old container, the error is wrapped as `failed to remove old container %s for image %s`.

Source

Thrown at pkg/skaffold/deploy/docker/deploy.go:168

	return nil
}

func (d *Deployer) ConfigName() string {
	return d.configName
}

// deploy creates a container in the local docker daemon from a build artifact's image.
func (d *Deployer) deploy(ctx context.Context, out io.Writer, artifact graph.Artifact) error {
	if !stringslice.Contains(d.cfg.Images, artifact.ImageName) {
		// TODO(nkubala)[07/20/21]: should we error out in this case?
		olog.Entry(ctx).Warnf("skipping deploy for image %s since it was not built by Skaffold", artifact.ImageName)
		return nil
	}
	if container, found := d.tracker.ContainerForImage(artifact.ImageName); found {
		olog.Entry(ctx).Debugf("removing old container %s for image %s", container.ID, artifact.ImageName)
		if err := d.client.Delete(ctx, out, container.ID); err != nil {
			return fmt.Errorf("failed to remove old container %s for image %s: %w", container.ID, artifact.ImageName, err)
		}
		d.portManager.RelinquishPorts(container.Name)
	}
	if d.cfg.UseCompose {
		// TODO(nkubala): implement
		return fmt.Errorf("docker compose not yet supported by skaffold")
	}

	containerCfg, err := d.containerConfigFromImage(ctx, artifact.Tag)
	if err != nil {
		return err
	}

	containerName := d.getContainerName(ctx, artifact.ImageName)
	opts := dockerutil.ContainerCreateOpts{
		Name:            containerName,
		Network:         d.network,
		ContainerConfig: containerCfg,

View on GitHub (pinned to a1189de023)

Solutions

  1. Manually remove the stale container: `docker rm -f <containerID>` then redeploy
  2. If the tracker is stale (container already gone), the ID may be dangling — run `docker container prune` and retry
  3. Check `docker ps -a` for containers stuck in a removing state and resolve dependents (volumes, networks)
  4. Restart the Docker daemon if removal requests hang

Example fix

// shell fix
docker rm -f <container-id>
skaffold dev
Defensive patterns

Strategy: retry

Validate before calling

id := tracker.ContainerForImage(imageName)
if id != "" {
    if out, err := exec.Command("docker", "inspect", id).CombinedOutput(); err != nil {
        // stale tracker entry; container already gone — safe to proceed or prune
        _ = out
    }
}

Try / catch

err := skaffoldDeploy()
if err != nil && strings.Contains(err.Error(), "failed to remove old container") {
    // extract container id and force-remove, then retry deploy
    if id := extractContainerID(err); id != "" {
        exec.Command("docker", "rm", "-f", id).Run()
    }
    err = skaffoldDeploy()
}

Prevention

When it happens

Trigger: The previously deployed container cannot be deleted — e.g. Docker daemon reports it as in-use, is in a removing/restarting state, the container ID no longer exists (stale tracker state), or daemon connectivity/permission issues.

Common situations: Stale skaffold state after a killed run leaving a ghost container reference; container is being removed concurrently (`removal in progress`); Docker daemon restart mid-deploy; volume mounts or other containers attached preventing removal.

Related errors


AI-assisted analysis of GoogleContainerTools/skaffold@a1189de023 (2026-09-05). Data as JSON: /api/errors/236d1b39dbbb5248. Report an issue: GitHub.