docker/compose · error

finalizing %q: %w

Error message

finalizing %q: %w

What it means

writeEntry explicitly calls tar.Writer.Flush after each entry so invalid entries are detected now rather than corrupting a later write. 'finalizing %q' means the flush of that entry's bytes to the underlying pipe failed or the writer detected an inconsistency (e.g. fewer bytes written than the header promised).

Source

Thrown at internal/sync/tar.go:242

	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)
	}

	if err != nil && !errors.Is(err, io.EOF) {
		return fmt.Errorf("copying %q: %w", pathInTar, err)
	}

	// explicitly flush so that if the entry is invalid we will detect it now and
	// provide a more meaningful error
	if err := a.tw.Flush(); err != nil {
		return fmt.Errorf("finalizing %q: %w", pathInTar, err)
	}
	return nil
}

// entriesForPath writes the given source path into tarWriter at the given dest (recursively for directories).
// e.g. tarring my_dir --> dest d: d/file_a, d/file_b
// If source path does not exist, quietly skips it and returns no err
func (a *ArchiveBuilder) entriesForPath(localPath, containerPath string) ([]archiveEntry, error) {
	localInfo, err := os.Stat(localPath)
	if err != nil {
		if os.IsNotExist(err) {
			return nil, nil
		}
		return nil, err
	}

	localPathIsDir := localInfo.IsDir()
	if localPathIsDir {

View on GitHub (pinned to ddc4b044b6)

Solutions

  1. Treat the wrapped cause like errors 107/108: pipe-closed -> fix the container side; short-write -> stabilize the source file
  2. Retry the full sync after remediation; a flush failure invalidates the archive being streamed
  3. Keep the target container running and non-paused for the whole sync window
  4. Exclude volatile large files from hot sync paths or sync them at quiet moments
Defensive patterns

Strategy: try-catch

Validate before calling

null // flush outcome cannot be pre-validated

Try / catch

// 'finalizing %q' -> check consumer liveness and source stability, remediate, re-invoke Sync (archive is invalid after flush failure)

Prevention

When it happens

Trigger: a.tw.Flush() failing: the io.Pipe writer end returned an error (Untar consumer already closed), or the buffered writer detected a short write for the entry (size mismatch from a file modified mid-copy on the >5MB path).

Common situations: Consumer-side failure (container exited mid-extract) surfacing at flush time; large file truncated between stat and copy so the promised header size was never delivered.

Related errors


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