{"record":{"id":"8976bf291708ec41","repo":"containerd/containerd","slug":"failed-to-write-file-header-w","errorCode":null,"errorMessage":"failed to write file header: %w","messagePattern":"failed to write file header: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/archive/tar.go","lineNumber":658,"sourceCode":"\t\t} else if k == fs.ChangeKindUnmodified {\n\t\t\t// Nothing to write to diff\n\t\t\treturn nil\n\t\t}\n\n\t\tif capability, err := getxattr(source, \"security.capability\"); err != nil {\n\t\t\treturn fmt.Errorf(\"failed to get capabilities xattr: %w\", err)\n\t\t} else if len(capability) > 0 {\n\t\t\tif hdr.PAXRecords == nil {\n\t\t\t\thdr.PAXRecords = map[string]string{}\n\t\t\t}\n\t\t\thdr.PAXRecords[paxSchilyXattr+\"security.capability\"] = string(capability)\n\t\t}\n\n\t\tif err := cw.includeParents(hdr); err != nil {\n\t\t\treturn err\n\t\t}\n\t\tif err := cw.tw.WriteHeader(hdr); err != nil {\n\t\t\treturn fmt.Errorf(\"failed to write file header: %w\", err)\n\t\t}\n\n\t\tif hdr.Typeflag == tar.TypeReg && hdr.Size > 0 {\n\t\t\tfile, err := open(source)\n\t\t\tif err != nil {\n\t\t\t\treturn fmt.Errorf(\"failed to open path: %v: %w\", source, err)\n\t\t\t}\n\t\t\tdefer file.Close()\n\n\t\t\tn, err := copyBuffered(context.TODO(), cw.tw, file)\n\t\t\tif err != nil {\n\t\t\t\treturn fmt.Errorf(\"failed to copy: %v: %w\", source, err)\n\t\t\t}\n\t\t\tif n != hdr.Size {\n\t\t\t\treturn errors.New(\"short write copying file\")\n\t\t\t}\n\t\t}\n","sourceCodeStart":640,"sourceCodeEnd":676,"githubUrl":"https://github.com/containerd/containerd/blob/4246446a2bf7d03837b0244118d858799393bd80/pkg/archive/tar.go#L640-L676","documentation":"After computing the header and writing parent directories, HandleChange writes the tar header with cw.tw.WriteHeader. Any tar writer failure (underlying writer error, write-after-close, out-of-space on the sink) is wrapped with this message so the caller knows header serialization failed rather than file content copy.","triggerScenarios":"tw.WriteHeader returns an error — typically the underlying io.Writer of the tar writer failed (pipe closed, disk full, connection broken), or WriteHeader is invoked on a tar.Writer already closed by a prior error.","commonSituations":"Consumer of the tar stream closed the pipe early; disk full while streaming to a file; concurrent Close of the ChangeWriter while HandleChange is still processing changes.","solutions":["Check the wrapped inner error from the tar writer","Ensure the destination writer stays open until ChangeWriter.Close completes","Do not call Close concurrently with HandleChange","Check available disk space or downstream transport health"],"exampleFix":"// before\npr, pw := io.Pipe()\ngo func(){ cw.Close(); pw.Close() }() // closes early\n// after\ngo func(){ defer pw.Close(); if err := cw.Close(); err != nil { log.Error(err) } }()","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"pr, pw := io.Pipe()\ndone := make(chan error, 1)\ngo func() {\n    defer close(done)\n    _, err := io.Copy(consumer, pr)\n    if err != nil { pr.CloseWithError(err) } // propagate sink errors upstream\n}()\nif err := w.HandleChange(kind, path, fi); err != nil {\n    return fmt.Errorf(\"tar header write failed for %s: %w\", path, err)\n}","preventionTips":["Never Close the ChangeWriter while HandleChange is running","Keep the tar consumer reading for the lifetime of the diff","Check disk space / transport health before large diffs","Surface errors from the reading side back into the pipe"],"tags":["archive","tar","io","streaming"],"backgroundTag":"tar-write-failed","analyzedSha":"4246446a2bf7d03837b0244118d858799393bd80","analyzedAt":"2026-09-02T00:14:43.053Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-09T06:17:21.866Z"}