{"record":{"id":"276a9ce96fc34409","repo":"GoogleContainerTools/skaffold","slug":"deleting-files-w","errorCode":null,"errorMessage":"deleting files: %w","messagePattern":"deleting files: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/skaffold/sync/docker.go","lineNumber":46,"sourceCode":"\ntype ContainerSyncer struct{}\n\nfunc NewContainerSyncer() *ContainerSyncer {\n\treturn &ContainerSyncer{}\n}\n\nfunc (s *ContainerSyncer) Sync(ctx context.Context, _ io.Writer, item *Item) error {\n\tif len(item.Copy) > 0 {\n\t\tlog.Entry(ctx).Info(\"Copying files:\", item.Copy, \"to\", item.Image)\n\t\tif _, err := util.RunCmdOut(ctx, s.copyFileFn(ctx, item.Artifact.ImageName, item.Copy)); err != nil {\n\t\t\treturn fmt.Errorf(\"copying files: %w\", err)\n\t\t}\n\t}\n\n\tif len(item.Delete) > 0 {\n\t\tlog.Entry(ctx).Info(\"Deleting files:\", item.Delete, \"from\", item.Image)\n\t\tif _, err := util.RunCmdOut(ctx, s.deleteFileFn(ctx, item.Artifact.ImageName, item.Delete)); err != nil {\n\t\t\treturn fmt.Errorf(\"deleting files: %w\", err)\n\t\t}\n\t}\n\n\treturn nil\n}\n\nfunc (s *ContainerSyncer) deleteFileFn(ctx context.Context, containerName string, files syncMap) *exec.Cmd {\n\tvar args []string\n\targs = append(args, \"exec\", \"-i\", containerName, \"rm\", \"-rf\", \"--\")\n\tfor _, dsts := range files {\n\t\targs = append(args, dsts...)\n\t}\n\treturn exec.CommandContext(ctx, \"docker\", args...)\n}\n\nfunc (s *ContainerSyncer) copyFileFn(ctx context.Context, containerName string, files syncMap) *exec.Cmd {\n\treader, writer := io.Pipe()\n\tgo func() {","sourceCodeStart":28,"sourceCodeEnd":64,"githubUrl":"https://github.com/GoogleContainerTools/skaffold/blob/a1189de023efc32d4b8e11f395acc678aa555011/pkg/skaffold/sync/docker.go#L28-L64","documentation":"`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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Verify the container is running and the image name matches the running container.","Check the container filesystem is writable (not readOnlyRootFilesystem) and the container user can delete the paths.","Trigger a full rebuild/redeploy instead of file sync if the deleted file is baked into the image and critical.","Ensure docker/kubectl CLI is installed and the daemon/cluster is reachable."],"exampleFix":"// before\nsecurityContext:\n  readOnlyRootFilesystem: true // rm inside container fails\n// after\nsecurityContext:\n  readOnlyRootFilesystem: false // or mount an emptyDir at the affected path","handlingStrategy":"try-catch","validationCode":"rw, _, err := exec.Command(\"docker\", \"inspect\", \"-f\", \"{{.HostConfig.ReadonlyRootfs}}\", imageName).Output()\nif err == nil && strings.TrimSpace(string(rw)) == \"true\" {\n  return fmt.Errorf(\"container rootfs is read-only; delete sync will fail\")\n}","typeGuard":null,"tryCatchPattern":"err := syncer.Sync(ctx, out, item)\nif err != nil {\n  if strings.Contains(err.Error(), \"deleting files\") {\n    log.Printf(\"delete sync failed (%v); falling back to rebuild\", err)\n    return triggerRebuild(item.Artifact)\n  }\n  return err\n}","preventionTips":["Avoid readOnlyRootFilesystem on containers you hot-sync deletions into, or mount a writable volume at those paths.","Ensure the container's user has write permission on synced directories.","Confirm the container wasn't restarted/exited before the sync fires.","Use manual sync rules scoped to writable paths only."],"tags":["file-sync","docker","containers","go"],"backgroundTag":"container-file-sync-failed","analyzedSha":"a1189de023efc32d4b8e11f395acc678aa555011","analyzedAt":"2026-09-05T12:09:27.064Z","contentChangedAt":"2026-09-05T12:09:27.064Z","schemaVersion":2},"datasetVersion":"2026-09-12T17:17:11.597Z"}