docker/compose · error
writing %q header: %w
Error message
writing %q header: %w
What it means
For non-regular files (directories, symlinks, fifos), writeEntry only writes a tar header. If tar.Writer.WriteHeader fails, the entry path is reported with 'writing %q header'. Typical cause: the underlying pipe writer errored (consumer side closed/failed) so all subsequent header writes fail, or the header itself is invalid (bad name, unsupported typeflag after go-archive filtering).
Source
Thrown at internal/sync/tar.go:180
entries = dedupeEntries(entries)
for _, entry := range entries {
err := a.writeEntry(entry)
if err != nil {
return fmt.Errorf("archiving %q: %w", entry.path, err)
}
}
return nil
}
func (a *ArchiveBuilder) writeEntry(entry archiveEntry) error {
pathInTar := entry.path
header := entry.header
if header.Typeflag != tar.TypeReg {
// anything other than a regular file (e.g. dir, symlink) just needs the header
if err := a.tw.WriteHeader(header); err != nil {
return fmt.Errorf("writing %q header: %w", pathInTar, err)
}
return nil
}
file, err := os.Open(pathInTar)
if err != nil {
// In case the file has been deleted since we last looked at it.
if os.IsNotExist(err) {
return nil
}
return err
}
defer func() {
_ = file.Close()
}()
// The size header must match the number of contents bytes.View on GitHub (pinned to ddc4b044b6)
Solutions
- Read the wrapped cause: if it is a pipe closed error, the real problem is on the Untar/container side — follow error 102's diagnosis for that container
- Ensure the destination container stays alive for the duration of the sync
- If the named entry is an odd file type (socket, device), exclude it from the sync mapping since it cannot be represented in tar
- Retry after the container-side issue is fixed; a poisoned writer never recovers within one archive build
Defensive patterns
Strategy: try-catch
Validate before calling
null // header failure is a downstream symptom of a poisoned writer; cannot be pre-validated cheaply
Try / catch
// if the wrapped error contains 'closed pipe', skip local fixes and diagnose the Untar consumer (container) instead
if strings.Contains(err.Error(), "pipe") { diagnoseContainer() } else { checkEntry(path) } Prevention
- Keep consumers alive for the archive's lifetime
- Exclude sockets/devices from synced trees
When it happens
Trigger: a.tw.WriteHeader(header) failing for a Typeflag != tar.TypeReg entry — usually because the io.Pipe reader (the Untar side) has closed with an error, or the archive/tar writer was already poisoned by a previous failed write.
Common situations: The container-side Untar died first (container stopped) so the pipe broke and every following header write in the builder goroutine fails with the wrapped pipe error; or an exotic file type produced an unusable header.
Related errors
AI-assisted analysis of docker/compose@ddc4b044b6 (2026-08-15).
Data as JSON: /api/errors/07f7b064703b4019.
Report an issue: GitHub.