{"record":{"id":"19a51afe1cd52f01","repo":"docker/compose","slug":"copying-q-w","errorCode":null,"errorMessage":"copying %q: %w","messagePattern":"copying %q: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/sync/tar.go","lineNumber":216,"sourceCode":"\t// The size header must match the number of contents bytes.\n\t//\n\t// There is room for a race condition here if something writes to the file\n\t// after we've read the file size.\n\t//\n\t// For small files, we avoid this by first copying the file into a buffer,\n\t// and using the size of the buffer to populate the header.\n\t//\n\t// For larger files, we don't want to copy the whole thing into a buffer,\n\t// because that would blow up heap size. There is some danger that this\n\t// will lead to a spurious error when the tar writer validates the sizes.\n\t// That error will be disruptive but will be handled as best as we\n\t// can downstream.\n\tuseBuf := header.Size < 5000000\n\tif useBuf {\n\t\ta.copyBuf.Reset()\n\t\t_, err = io.Copy(a.copyBuf, file)\n\t\tif err != nil && !errors.Is(err, io.EOF) {\n\t\t\treturn fmt.Errorf(\"copying %q: %w\", pathInTar, err)\n\t\t}\n\t\theader.Size = int64(len(a.copyBuf.Bytes()))\n\t}\n\n\t// wait to write the header until _after_ the file is successfully opened\n\t// to avoid generating an invalid tar entry that has a header but no contents\n\t// in the case the file has been deleted\n\terr = a.tw.WriteHeader(header)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"writing %q header: %w\", pathInTar, err)\n\t}\n\n\tif useBuf {\n\t\t_, err = io.Copy(a.tw, a.copyBuf)\n\t} else {\n\t\t_, err = io.Copy(a.tw, file)\n\t}\n","sourceCodeStart":198,"sourceCodeEnd":234,"githubUrl":"https://github.com/docker/compose/blob/ddc4b044b62e9f715212ea4143fa830fac76382f/internal/sync/tar.go#L198-L234","documentation":"For regular files smaller than 5,000,000 bytes, writeEntry buffers the whole file (io.Copy into a reused copyBuf) so the header size can be corrected. If reading the file fails with anything other than EOF, you get 'copying %q'. Reading a local file into memory failed mid-file.","triggerScenarios":"io.Copy(a.copyBuf, file) returning a non-EOF error: the file shrank or was truncated while being read, the filesystem raised EIO, or the file was swapped for one the process cannot fully read between open and copy.","commonSituations":"Watch-mode syncing while a build tool rewrites small files in place (truncate + rewrite), flaky disks, or files on NFS/FUSE mounts with read errors.","solutions":["Check dmesg/system logs for filesystem errors on the named path if EIO is suspected","Retarget generators that truncate-rewrite to write-to-temp-then-rename so readers never see a partially written file","Retry the sync once the source file is stable; the next walk picks up a consistent copy","If the path is on a network mount, sync from a local checkout or fix the mount"],"exampleFix":null,"handlingStrategy":"retry","validationCode":"null // mid-read file changes cannot be predicted; only stabilized sources prevent it","typeGuard":null,"tryCatchPattern":"// catch, check named path still exists and is stable (two stats, same size/mtime), then re-run the sync once","preventionTips":["Configure generators to write temp-then-rename","Pause builds while hot-syncing small files"],"tags":["filesystem","tar","sync","io","go"],"backgroundTag":null,"analyzedSha":"ddc4b044b62e9f715212ea4143fa830fac76382f","analyzedAt":"2026-08-15T13:31:42.319Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}