docker/compose · error

copying %q: %w

Error message

copying %q: %w

What it means

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.

Source

Thrown at internal/sync/tar.go:216

	// The size header must match the number of contents bytes.
	//
	// There is room for a race condition here if something writes to the file
	// after we've read the file size.
	//
	// For small files, we avoid this by first copying the file into a buffer,
	// and using the size of the buffer to populate the header.
	//
	// For larger files, we don't want to copy the whole thing into a buffer,
	// because that would blow up heap size. There is some danger that this
	// will lead to a spurious error when the tar writer validates the sizes.
	// That error will be disruptive but will be handled as best as we
	// can downstream.
	useBuf := header.Size < 5000000
	if useBuf {
		a.copyBuf.Reset()
		_, err = io.Copy(a.copyBuf, file)
		if err != nil && !errors.Is(err, io.EOF) {
			return fmt.Errorf("copying %q: %w", pathInTar, err)
		}
		header.Size = int64(len(a.copyBuf.Bytes()))
	}

	// wait to write the header until _after_ the file is successfully opened
	// to avoid generating an invalid tar entry that has a header but no contents
	// in the case the file has been deleted
	err = a.tw.WriteHeader(header)
	if err != nil {
		return fmt.Errorf("writing %q header: %w", pathInTar, err)
	}

	if useBuf {
		_, err = io.Copy(a.tw, a.copyBuf)
	} else {
		_, err = io.Copy(a.tw, file)
	}

View on GitHub (pinned to ddc4b044b6)

Solutions

  1. Check dmesg/system logs for filesystem errors on the named path if EIO is suspected
  2. Retarget generators that truncate-rewrite to write-to-temp-then-rename so readers never see a partially written file
  3. Retry the sync once the source file is stable; the next walk picks up a consistent copy
  4. If the path is on a network mount, sync from a local checkout or fix the mount
Defensive patterns

Strategy: retry

Validate before calling

null // mid-read file changes cannot be predicted; only stabilized sources prevent it

Try / catch

// catch, check named path still exists and is stable (two stats, same size/mtime), then re-run the sync once

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of docker/compose@ddc4b044b6 (2026-08-15). Data as JSON: /api/errors/19a51afe1cd52f01. Report an issue: GitHub.