{"record":{"id":"96f8d4f823ff58c1","repo":"docker/compose","slug":"copying-files-to-s-w","errorCode":null,"errorMessage":"copying files to %s: %w","messagePattern":"copying files to (.+?): %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/sync/tar.go","lineNumber":112,"sourceCode":"\t)\n\n\teg.SetLimit(16) // arbitrary limit, adjust to taste :D\n\tfor i := range containers {\n\t\tcontainerID := containers[i].ID\n\t\ttarReader := tarArchive(pathsToCopy)\n\n\t\teg.Go(func() error {\n\t\t\tif len(deleteCmd) != 0 {\n\t\t\t\tif err := t.client.Exec(ctx, containerID, deleteCmd, nil); err != nil {\n\t\t\t\t\terrMu.Lock()\n\t\t\t\t\terrs = append(errs, fmt.Errorf(\"deleting paths in %s: %w\", containerID, err))\n\t\t\t\t\terrMu.Unlock()\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif err := t.client.Untar(ctx, containerID, tarReader); err != nil {\n\t\t\t\terrMu.Lock()\n\t\t\t\terrs = append(errs, fmt.Errorf(\"copying files to %s: %w\", containerID, err))\n\t\t\t\terrMu.Unlock()\n\t\t\t}\n\t\t\treturn nil // don't fail-fast; collect all errors\n\t\t})\n\t}\n\n\t_ = eg.Wait()\n\treturn errors.Join(errs...)\n}\n\ntype ArchiveBuilder struct {\n\ttw *tar.Writer\n\t// A shared I/O buffer to help with file copying.\n\tcopyBuf *bytes.Buffer\n}\n\nfunc NewArchiveBuilder(writer io.Writer) *ArchiveBuilder {\n\ttw := tar.NewWriter(writer)","sourceCodeStart":94,"sourceCodeEnd":130,"githubUrl":"https://github.com/docker/compose/blob/ddc4b044b62e9f715212ea4143fa830fac76382f/internal/sync/tar.go#L94-L130","documentation":"After the (optional) delete step, Tar.Sync streams a freshly built tar of the changed files into each container via LowLevelClient.Untar (docker's put-archive equivalent). Any failure copying/extracting is collected per container and joined into the final error. Two errors per container are possible (delete + copy); this one means the tar upload/extraction itself failed.","triggerScenarios":"t.client.Untar(ctx, containerID, tarReader) failing: container gone or stopped between list and copy, disk full in the container, destination path is not a directory or is read-only, corrupted tar stream (writer goroutine errored, surfacing here as a pipe read error), or the container's archive-extract API returning an error.","commonSituations":"Containers restarting under 'docker compose up --watch' while a sync fires, full container overlay filesystems, syncing a file onto a path that is a mounted directory, or a host file disappearing mid-tar producing a pipe error propagated to the Untar side.","solutions":["Verify the container is running: docker ps --filter id=<id from message>; restart it and retrigger the sync","Check the container's rootfs space and the target container path is a writable directory: docker exec <id> df -h / <dest>","Look at the joined sibling errors: an 'adding files to tar' error means the real failure was on the archive-builder goroutine (e.g. file vanished), fix the host side","Inspect dockerd logs for the failed PUT /archive call if the container looks healthy"],"exampleFix":null,"handlingStrategy":"retry","validationCode":"// preflight before Untar loop: confirm containers are running and target dir writable\nfor _, c := range containers {\n    if c.State != \"running\" { waitOrRestart(c.ID) }\n}","typeGuard":null,"tryCatchPattern":"// joined errors: identify 'copying files to <id>' entries, unwrap to the pipe/exec cause, restart that container, then re-invoke Sync once","preventionTips":["Ensure the destination directory exists and is writable in the image","Monitor container disk usage when syncing large artifacts","Pair this error with its producer-side twin (errors 112/113) before choosing a fix"],"tags":["containers","tar","sync","disk-full","go"],"backgroundTag":null,"analyzedSha":"ddc4b044b62e9f715212ea4143fa830fac76382f","analyzedAt":"2026-08-15T13:31:42.319Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}