GoogleContainerTools/skaffold · error

deleting files: %w

Error message

deleting files: %w

What it means

`ContainerSyncer.Sync` wraps failures from running the delete command (`s.deleteFileFn`) used to remove deleted files from inside the running container during file sync. The sync of file deletions to the container failed, so the incremental sync did not fully apply.

Source

Thrown at pkg/skaffold/sync/docker.go:46

type ContainerSyncer struct{}

func NewContainerSyncer() *ContainerSyncer {
	return &ContainerSyncer{}
}

func (s *ContainerSyncer) Sync(ctx context.Context, _ io.Writer, item *Item) error {
	if len(item.Copy) > 0 {
		log.Entry(ctx).Info("Copying files:", item.Copy, "to", item.Image)
		if _, err := util.RunCmdOut(ctx, s.copyFileFn(ctx, item.Artifact.ImageName, item.Copy)); err != nil {
			return fmt.Errorf("copying files: %w", err)
		}
	}

	if len(item.Delete) > 0 {
		log.Entry(ctx).Info("Deleting files:", item.Delete, "from", item.Image)
		if _, err := util.RunCmdOut(ctx, s.deleteFileFn(ctx, item.Artifact.ImageName, item.Delete)); err != nil {
			return fmt.Errorf("deleting files: %w", err)
		}
	}

	return nil
}

func (s *ContainerSyncer) deleteFileFn(ctx context.Context, containerName string, files syncMap) *exec.Cmd {
	var args []string
	args = append(args, "exec", "-i", containerName, "rm", "-rf", "--")
	for _, dsts := range files {
		args = append(args, dsts...)
	}
	return exec.CommandContext(ctx, "docker", args...)
}

func (s *ContainerSyncer) copyFileFn(ctx context.Context, containerName string, files syncMap) *exec.Cmd {
	reader, writer := io.Pipe()
	go func() {

View on GitHub (pinned to a1189de023)

Solutions

  1. Verify the container is running and the image name matches the running container.
  2. Check the container filesystem is writable (not readOnlyRootFilesystem) and the container user can delete the paths.
  3. Trigger a full rebuild/redeploy instead of file sync if the deleted file is baked into the image and critical.
  4. Ensure docker/kubectl CLI is installed and the daemon/cluster is reachable.

Example fix

// before
securityContext:
  readOnlyRootFilesystem: true // rm inside container fails
// after
securityContext:
  readOnlyRootFilesystem: false // or mount an emptyDir at the affected path
Defensive patterns

Strategy: try-catch

Validate before calling

rw, _, err := exec.Command("docker", "inspect", "-f", "{{.HostConfig.ReadonlyRootfs}}", imageName).Output()
if err == nil && strings.TrimSpace(string(rw)) == "true" {
  return fmt.Errorf("container rootfs is read-only; delete sync will fail")
}

Try / catch

err := syncer.Sync(ctx, out, item)
if err != nil {
  if strings.Contains(err.Error(), "deleting files") {
    log.Printf("delete sync failed (%v); falling back to rebuild", err)
    return triggerRebuild(item.Artifact)
  }
  return err
}

Prevention

When it happens

Trigger: Calling `Sync` with a non-empty `Delete` list while the container is not running, the image/container reference is invalid, the underlying CLI (`docker exec rm`, etc.) fails due to permissions or a read-only filesystem inside the container.

Common situations: Deleting a file locally while the container has a read-only root filesystem (readOnlyRootFilesystem securityContext); container restarted between build and sync; container user lacks permission to remove the path; docker daemon unavailable.

Related errors


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