GoogleContainerTools/skaffold · error

copying files: %w

Error message

copying files: %w

What it means

PodSyncer.sync performs the actual copy of changed files into the running pod container(s) via Perform with the copyFileFn. When that kubectl-based copy fails, Skaffold wraps the error as 'copying files'. The syncMap (container path -> local paths) comes from the item being synced.

Source

Thrown at pkg/skaffold/sync/sync.go:311

	hooksRunner := hooks.NewSyncRunner(s.kubectl, item.Artifact.ImageName, item.Image, *s.namespaces, s.formatter, item.Artifact.Sync.LifecycleHooks, opts)
	if err := hooksRunner.RunPreHooks(ctx, out); err != nil {
		return fmt.Errorf("pre-sync hooks failed for artifact %q: %w", item.Artifact.ImageName, err)
	}
	if err := s.sync(ctx, item); err != nil {
		return err
	}
	if err := hooksRunner.RunPostHooks(ctx, out); err != nil {
		return fmt.Errorf("post-sync hooks failed for artifact %q: %w", item.Artifact.ImageName, err)
	}
	return nil
}

func (s *PodSyncer) sync(ctx context.Context, item *Item) error {
	if len(item.Copy) > 0 {
		log.Entry(ctx).Info("Copying files:", item.Copy, "to", item.Image)

		if err := Perform(ctx, item.Image, item.Copy, s.copyFileFn, *s.namespaces, s.kubectl.KubeContext); 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 := Perform(ctx, item.Image, item.Delete, s.deleteFileFn, *s.namespaces, s.kubectl.KubeContext); err != nil {
			return fmt.Errorf("deleting files: %w", err)
		}
	}

	return nil
}

func Perform(ctx context.Context, image string, files syncMap, cmdFn func(context.Context, v1.Pod, v1.Container, syncMap) *exec.Cmd, namespaces []string, kubeContext string) error {
	if len(files) == 0 {
		return nil
	}

View on GitHub (pinned to a1189de023)

Solutions

  1. Run `kubectl get pods` to confirm the target pod is Running and not crash-looping, then retry the sync
  2. Test the copy manually (kubectl cp local.txt pod:/dest/) to expose RBAC or path-permission errors
  3. Check destination path writability in the image and correct the `dest:` in sync rules; verify kube context connectivity

Example fix

// before
sync:
  manual:
    - src: '**/*.go'
      dest: /go/src/   # read-only layer path in image
// after
sync:
  manual:
    - src: '**/*.go'
      dest: /app/src/
Defensive patterns

Strategy: retry

Validate before calling

// confirm pod is ready before syncing
out, err := exec.Command("kubectl", "get", "pod", pod, "-o", "jsonpath={.status.phase}").Output()
if err != nil || string(out) != "Running" { return errors.New("pod not ready for sync") }

Try / catch

err := s.Sync(ctx, out, names, item)
if err != nil {
    if strings.Contains(err.Error(), "copying files") {
        select {
        case <-time.After(2 * time.Second):
            return s.Sync(ctx, out, names, item) // pod may have restarted; retry once
        default:
        }
    }
    return err
}

Prevention

When it happens

Trigger: Perform fails while kubectl-cp-ing files into the pod: pod restarting/evicted, container not running, kubectl exec/put network failure, or destination path not writable in the container.

Common situations: Pod in CrashLoopBackOff so cp target is gone; RBAC lacking exec/patch permissions on pods; destination directory read-only in the image; intermittent cluster connectivity during heavy file-change bursts.

Related errors


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