nektos/act · error

failed to remove image '%s'

Error message

failed to remove image '%s'

What it means

Thrown by execAsDocker in pkg/runner/action.go when a Docker action image exists locally only for a different architecture. act calls container.RemoveImage(ctx, image, true, true) to prune the wrong-arch image; RemoveImage returns (false, nil) when the Docker remove call reports the image was already gone (e.g. raced/untagged) but no hard error occurred, so act cannot proceed to rebuild the correct-architecture image from a clean state.

Source

Thrown at pkg/runner/action.go:283

		contextDir, fileName := path.Split(path.Join(subpath, action.Runs.Image))

		anyArchExists, err := container.ImageExistsLocally(ctx, image, "any")
		if err != nil {
			return err
		}

		correctArchExists, err := container.ImageExistsLocally(ctx, image, rc.Config.ContainerArchitecture)
		if err != nil {
			return err
		}

		if anyArchExists && !correctArchExists {
			wasRemoved, err := container.RemoveImage(ctx, image, true, true)
			if err != nil {
				return err
			}
			if !wasRemoved {
				return fmt.Errorf("failed to remove image '%s'", image)
			}
		}

		if !correctArchExists || rc.Config.ForceRebuild {
			logger.Debugf("image '%s' for architecture '%s' will be built from context '%s", image, rc.Config.ContainerArchitecture, contextDir)
			var buildContext io.ReadCloser
			if localAction {
				buildContext, err = rc.JobContainer.GetContainerArchive(ctx, contextDir+"/.")
				if err != nil {
					return err
				}
				defer buildContext.Close()
			} else if rc.Config.ActionCache != nil {
				rstep := step.(*stepActionRemote)
				buildContext, err = rc.Config.ActionCache.GetTarArchive(ctx, rstep.cacheDir, rstep.resolvedSha, contextDir)
				if err != nil {
					return err
				}

View on GitHub (pinned to 4f41128141)

Solutions

  1. Manually remove the conflicting image: docker rmi -f <image> (the image name is printed in the error), then re-run act.
  2. Run 'docker image prune -f' to clear dangling/wrong-arch layers that Docker cannot remove by name.
  3. Avoid mixing --container-architecture values against the same cached action images; clear ~/.cache/act or the action cache dir when switching architectures.
  4. If it persists, inspect 'docker images -a | grep <image>' for duplicate/untagged entries and remove them by ID.

Example fix

# before (workflow run fails)
act -P ubuntu-latest=catthehacker/ubuntu-latest:act-latest  # after previously using arm64 image

# after (shell)
docker rmi -f $(docker images -q <image-from-error>)
act -P ubuntu-latest=catthehacker/ubuntu-latest:act-latest
Defensive patterns

Strategy: validation

Validate before calling

docker images --format '{{.Repository}}:{{.Tag}} {{.ID}}' | grep '^<image-from-error>'
# if the arch column mismatches (docker inspect -f '{{.Architecture}}' <id>), remove before running act:
docker rmi -f $(docker images -q <image>)

Prevention

When it happens

Trigger: Running an action whose image was previously pulled for another platform (e.g. linux/amd64 cached while running with --container-architecture linux/arm64); the existence check for the correct arch fails, the any-arch check succeeds, and RemoveImage returns wasRemoved=false because 'docker rmi -f' reported NoSuchImage or the image was removed concurrently by another process.

Common situations: Switching between hosts/emulation (Apple Silicon vs x86), using -P/--container-architecture flags, running multiple act instances sharing one Docker daemon, or a stale dangling image entry that Docker refuses to remove.

Related errors


AI-assisted analysis of nektos/act@4f41128141 (2026-08-15). Data as JSON: /api/errors/4277792b455bb452. Report an issue: GitHub.