{"record":{"id":"07f7b064703b4019","repo":"docker/compose","slug":"writing-q-header-w","errorCode":null,"errorMessage":"writing %q header: %w","messagePattern":"writing %q header: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/sync/tar.go","lineNumber":180,"sourceCode":"\n\tentries = dedupeEntries(entries)\n\tfor _, entry := range entries {\n\t\terr := a.writeEntry(entry)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"archiving %q: %w\", entry.path, err)\n\t\t}\n\t}\n\treturn nil\n}\n\nfunc (a *ArchiveBuilder) writeEntry(entry archiveEntry) error {\n\tpathInTar := entry.path\n\theader := entry.header\n\n\tif header.Typeflag != tar.TypeReg {\n\t\t// anything other than a regular file (e.g. dir, symlink) just needs the header\n\t\tif err := a.tw.WriteHeader(header); err != nil {\n\t\t\treturn fmt.Errorf(\"writing %q header: %w\", pathInTar, err)\n\t\t}\n\t\treturn nil\n\t}\n\n\tfile, err := os.Open(pathInTar)\n\tif err != nil {\n\t\t// In case the file has been deleted since we last looked at it.\n\t\tif os.IsNotExist(err) {\n\t\t\treturn nil\n\t\t}\n\t\treturn err\n\t}\n\n\tdefer func() {\n\t\t_ = file.Close()\n\t}()\n\n\t// The size header must match the number of contents bytes.","sourceCodeStart":162,"sourceCodeEnd":198,"githubUrl":"https://github.com/docker/compose/blob/ddc4b044b62e9f715212ea4143fa830fac76382f/internal/sync/tar.go#L162-L198","documentation":"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).","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"null // header failure is a downstream symptom of a poisoned writer; cannot be pre-validated cheaply","typeGuard":null,"tryCatchPattern":"// if the wrapped error contains 'closed pipe', skip local fixes and diagnose the Untar consumer (container) instead\nif strings.Contains(err.Error(), \"pipe\") { diagnoseContainer() } else { checkEntry(path) }","preventionTips":["Keep consumers alive for the archive's lifetime","Exclude sockets/devices from synced trees"],"tags":["tar","sync","io-pipe","go"],"backgroundTag":null,"analyzedSha":"ddc4b044b62e9f715212ea4143fa830fac76382f","analyzedAt":"2026-08-15T13:31:42.319Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}