{"record":{"id":"ca33c7118d356eaa","repo":"docker/compose","slug":"finalizing-q-w","errorCode":null,"errorMessage":"finalizing %q: %w","messagePattern":"finalizing %q: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/sync/tar.go","lineNumber":242,"sourceCode":"\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\n\tif err != nil && !errors.Is(err, io.EOF) {\n\t\treturn fmt.Errorf(\"copying %q: %w\", pathInTar, err)\n\t}\n\n\t// explicitly flush so that if the entry is invalid we will detect it now and\n\t// provide a more meaningful error\n\tif err := a.tw.Flush(); err != nil {\n\t\treturn fmt.Errorf(\"finalizing %q: %w\", pathInTar, err)\n\t}\n\treturn nil\n}\n\n// entriesForPath writes the given source path into tarWriter at the given dest (recursively for directories).\n// e.g. tarring my_dir --> dest d: d/file_a, d/file_b\n// If source path does not exist, quietly skips it and returns no err\nfunc (a *ArchiveBuilder) entriesForPath(localPath, containerPath string) ([]archiveEntry, error) {\n\tlocalInfo, err := os.Stat(localPath)\n\tif err != nil {\n\t\tif os.IsNotExist(err) {\n\t\t\treturn nil, nil\n\t\t}\n\t\treturn nil, err\n\t}\n\n\tlocalPathIsDir := localInfo.IsDir()\n\tif localPathIsDir {","sourceCodeStart":224,"sourceCodeEnd":260,"githubUrl":"https://github.com/docker/compose/blob/ddc4b044b62e9f715212ea4143fa830fac76382f/internal/sync/tar.go#L224-L260","documentation":"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).","triggerScenarios":"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).","commonSituations":"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.","solutions":["Treat the wrapped cause like errors 107/108: pipe-closed -> fix the container side; short-write -> stabilize the source file","Retry the full sync after remediation; a flush failure invalidates the archive being streamed","Keep the target container running and non-paused for the whole sync window","Exclude volatile large files from hot sync paths or sync them at quiet moments"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"null // flush outcome cannot be pre-validated","typeGuard":null,"tryCatchPattern":"// 'finalizing %q' -> check consumer liveness and source stability, remediate, re-invoke Sync (archive is invalid after flush failure)","preventionTips":["Ensure the extract side never aborts early (space, permissions in container)","Avoid file mutation between stat and copy windows"],"tags":["tar","sync","io","go"],"backgroundTag":null,"analyzedSha":"ddc4b044b62e9f715212ea4143fa830fac76382f","analyzedAt":"2026-08-15T13:31:42.319Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}