{"record":{"id":"825a7de5c2f52425","repo":"vxcontrol/pentagi","slug":"failed-to-read-tar-entry-w","errorCode":null,"errorMessage":"failed to read tar entry: %w","messagePattern":"failed to read tar entry: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"backend/pkg/flowfiles/files.go","lineNumber":385,"sourceCode":"\n\treturn \"\"\n}\n\nfunc WriteUploadsTar(w *io.PipeWriter, uploadDir string) error {\n\treturn writeDirectoryTar(w, uploadDir, UploadsDirName, \"upload\", \"uploads\")\n}\n\nfunc ExtractTar(r io.Reader, destDir string) error {\n\ttr := tar.NewReader(r)\n\tvar filesCount int\n\tvar totalSize int64\n\tfor {\n\t\thdr, err := tr.Next()\n\t\tif err == io.EOF {\n\t\t\tbreak\n\t\t}\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"failed to read tar entry: %w\", err)\n\t\t}\n\t\tif hdr.Typeflag == tar.TypeSymlink || hdr.Typeflag == tar.TypeLink {\n\t\t\tcontinue\n\t\t}\n\n\t\tentryPath := filepath.Join(destDir, filepath.Clean(filepath.FromSlash(hdr.Name)))\n\t\tif !IsWithinDir(entryPath, destDir) {\n\t\t\tcontinue\n\t\t}\n\n\t\tswitch hdr.Typeflag {\n\t\tcase tar.TypeDir:\n\t\t\tif err := os.MkdirAll(entryPath, 0755); err != nil {\n\t\t\t\treturn fmt.Errorf(\"failed to create directory '%s': %w\", entryPath, err)\n\t\t\t}\n\t\tcase tar.TypeReg, tar.TypeRegA:\n\t\t\tif hdr.Size < 0 {\n\t\t\t\treturn fmt.Errorf(\"tar entry '%s' has invalid size %d\", hdr.Name, hdr.Size)","sourceCodeStart":367,"sourceCodeEnd":403,"githubUrl":"https://github.com/vxcontrol/pentagi/blob/ea665308baaff015b226f308438a68d929d0f29b/backend/pkg/flowfiles/files.go#L367-L403","documentation":"ExtractTar iterates a tar archive with tar.Reader.Next; this error wraps any tar-stream error that is not clean EOF — corrupted archive bytes, truncated stream, unsupported format, or an underlying read failure from the source reader. It fires before any entry-specific handling, so extraction aborts with whatever was already written left in destDir.","triggerScenarios":"PullFlowFiles receives an archive whose bytes are not valid tar: the producer wrote gzip but the consumer expects raw tar, the stream was truncated mid-transfer, the HTTP body was cut off, or the source pipe errored.","commonSituations":"Sender gzipped the tarball (gzip data read as tar gives 'tar: invalid tar header'); interrupted container-to-container copy; wrong Content-Encoding stripping; older/newer tar format incompatibilities (pax/gnu headers).","solutions":["Verify the archive is uncompressed tar — if the producer gzips, wrap the reader with gzip.NewReader(r) before ExtractTar.","Test the exact bytes with `tar -tvf archive.tar` locally to confirm corruption vs consumer bug.","Check the transfer path for truncation (proxy limits, closed pipes); ensure the writer closes the pipe/stream before extraction.","Regenerate the archive from the source with archive/tar or GNU tar defaults."],"exampleFix":"// before\nerr := flowfiles.ExtractTar(resp.Body, destDir)\n// after\nvar r io.Reader = resp.Body\nif strings.Contains(resp.Header.Get(\"Content-Type\"), \"gzip\") {\n    r, err = gzip.NewReader(resp.Body)\n    if err != nil { return err }\n}\nerr = flowfiles.ExtractTar(r, destDir)","handlingStrategy":"validation","validationCode":"// Verify the payload is uncompressed tar before extraction:\nbr := make([]byte, 262)\nn, _ := io.ReadFull(rc, br)\nif n < 262 {\n    return fmt.Errorf(\"stream too short to be a tar archive\")\n}\nif !bytes.Equal(br[257:262], []byte(\"ustar\")) {\n    // maybe gzipped — decompress first\n    gz, err := gzip.NewReader(io.MultiReader(bytes.NewReader(br[:n]), rc))\n    if err != nil {\n        return fmt.Errorf(\"not tar or gzip: %w\", err)\n    }\n    rc = gz\n} else {\n    rc = io.MultiReader(bytes.NewReader(br[:n]), rc)\n}","typeGuard":null,"tryCatchPattern":"err := flowfiles.ExtractTar(rc, destDir)\nif err != nil {\n    if strings.Contains(err.Error(), \"failed to read tar entry\") {\n        return fmt.Errorf(\"archive is corrupt, truncated, or not plain tar: %w\", err)\n    }\n    return err\n}","preventionTips":["Match compression end-to-end: if the producer gzips, always decompress before ExtractTar.","Verify archive integrity (checksum/sha256) before extraction on the receiving side.","Ensure writers close pipes/streams cleanly; avoid reading partially flushed archives.","Round-trip test archives with `tar -tvf` when debugging cross-service transfers."],"tags":["tar","archive","io","corruption"],"backgroundTag":"invalid-tar-archive","analyzedSha":"ea665308baaff015b226f308438a68d929d0f29b","analyzedAt":"2026-09-01T14:16:31.421Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}