{"record":{"id":"13bececbc681f034","repo":"wagoodman/dive","slug":"unexpected-tar-file-xglobalheader-type-v-name","errorCode":null,"errorMessage":"unexpected tar file: (XGlobalHeader): type=%v name=%s","messagePattern":"unexpected tar file: \\(XGlobalHeader\\): type=(.+?) name=(.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"dive/image/docker/image_archive.go","lineNumber":240,"sourceCode":"\tvar files []filetree.FileInfo\n\n\tfor {\n\t\theader, err := tarReader.Next()\n\t\tif err == io.EOF {\n\t\t\tbreak\n\t\t} else if err != nil {\n\t\t\treturn nil, err\n\t\t}\n\n\t\t// always ensure relative path notations are not parsed as part of the filename\n\t\tname := path.Clean(header.Name)\n\t\tif name == \".\" {\n\t\t\tcontinue\n\t\t}\n\n\t\tswitch header.Typeflag {\n\t\tcase tar.TypeXGlobalHeader:\n\t\t\treturn nil, fmt.Errorf(\"unexpected tar file: (XGlobalHeader): type=%v name=%s\", header.Typeflag, name)\n\t\tcase tar.TypeXHeader:\n\t\t\treturn nil, fmt.Errorf(\"unexpected tar file (XHeader): type=%v name=%s\", header.Typeflag, name)\n\t\tdefault:\n\t\t\tfiles = append(files, filetree.NewFileInfoFromTarHeader(tarReader, header, name))\n\t\t}\n\t}\n\treturn files, nil\n}\n\nfunc (img *ImageArchive) ToImage(id string) (*image.Image, error) {\n\ttrees := make([]*filetree.FileTree, 0)\n\n\t// build the content tree\n\tfor _, treeName := range img.manifest.LayerTarPaths {\n\t\ttr, exists := img.layerMap[treeName]\n\t\tif exists {\n\t\t\ttrees = append(trees, tr)\n\t\t\tcontinue","sourceCodeStart":222,"sourceCodeEnd":258,"githubUrl":"https://github.com/wagoodman/dive/blob/d6c691947f8fda635c952a17ee3b7555379d58f0/dive/image/docker/image_archive.go#L222-L258","documentation":"Returned while reading a layer tar (dive/image/docker/image_archive.go:240) when an entry has tar.Typeflag == tar.TypeXGlobalHeader (PAX global extended header). This dive version treats both global ('g') and per-file ('x') PAX extended headers as unexpected and refuses the layer outright. PAX headers are legal tar, so this is a format limitation, not a corrupt archive.","triggerScenarios":"Analyzing images whose layer tars were packed in POSIX/PAX format - GNU tar with --format=posix, buildkit/buildx stages emitting global headers, or build tools (some kaniko/nix/nerdctl paths) that write a pax_global_header entry.","commonSituations":"Images built with newer BuildKit versions or custom base-image pipelines suddenly failing dive CI though docker/podman handle them fine; reproducible-build setups that force POSIX tar format.","solutions":["Update dive - later releases skip or handle XGlobalHeader/XHeader entries instead of failing","Repack the layer tars in a tolerated format: extract and re-tar with --format=gnu (or ustar), then rebuild the archive","Rebuild the image with a builder setting that avoids PAX global headers (e.g. DOCKER_BUILDKIT=0 legacy builder, or tar --format=gnu in your image pipeline)","Confirm which entry trips it: tar -tvf <layer>.tar | head and look for pax_global_header"],"exampleFix":"# before (posix-format layer tar)\ntar --format=posix -cf layer.tar -C rootfs .\n# -> dive: unexpected tar file: (XGlobalHeader)\n\n# after\ntar --format=gnu -cf layer.tar -C rootfs .\n# (or simply upgrade dive, which skips global headers)","handlingStrategy":"fallback","validationCode":"// detect PAX global headers in layer tars before dive rejects them\nfunc layerTarsAreSafe(imageTar string) error {\n    for _, layerTar := range layerTarPathsIn(imageTar) {\n        f, err := os.Open(layerTar)\n        if err != nil {\n            return err\n        }\n        tr := tar.NewReader(f)\n        for {\n            hdr, err := tr.Next()\n            if err == io.EOF {\n                break\n            }\n            if err != nil {\n                return err\n            }\n            if hdr.Typeflag == tar.TypeXGlobalHeader || hdr.Typeflag == tar.TypeXHeader {\n                return fmt.Errorf(\"%s contains PAX extended headers\", layerTar)\n            }\n        }\n        f.Close()\n    }\n    return nil\n}","typeGuard":null,"tryCatchPattern":"_, pathErrs, err := analysis.Run(img) // layer processing surfaces this error\nif err != nil && strings.Contains(err.Error(), \"unexpected tar file\") {\n    // fallback: repack offending layers with GNU format and retry\n    if rerr := repackLayersAsGnu(imgTarPath); rerr == nil {\n        _, pathErrs, err = analysis.Run(reloadedImg) // retry once\n    }\n}\nif err != nil {\n    return err\n}","preventionTips":["Upgrade dive - newer builds tolerate PAX headers","Pin image-building tooling to tar formats dive accepts (gnu/ustar)","Add a dive CI step early so format regressions from builder updates surface fast"],"tags":["tar","pax","format-mismatch","layers","compatibility"],"backgroundTag":null,"analyzedSha":"d6c691947f8fda635c952a17ee3b7555379d58f0","analyzedAt":"2026-08-15T09:42:35.293Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}