{"record":{"id":"045ad939ca002f63","repo":"vxcontrol/pentagi","slug":"failed-to-read-tar-header-w","errorCode":null,"errorMessage":"failed to read tar header: %w","messagePattern":"failed to read tar header: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"backend/pkg/tools/terminal.go","lineNumber":388,"sourceCode":"\tif !isRunning {\n\t\treturn \"\", fmt.Errorf(\"container runtime is not operational\")\n\t}\n\n\treader, stats, err := t.dockerClient.CopyFromContainer(ctx, containerName, path)\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"failed to copy file: %w\", err)\n\t}\n\tdefer reader.Close()\n\n\tvar buffer strings.Builder\n\ttarReader := tar.NewReader(reader)\n\tfor {\n\t\ttarHeader, err := tarReader.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 header: %w\", err)\n\t\t}\n\n\t\tif tarHeader.FileInfo().IsDir() {\n\t\t\tcontinue\n\t\t}\n\n\t\tif stats.Mode.IsDir() {\n\t\t\tbuffer.WriteString(\"--------------------------------------------------\\n\")\n\t\t\tbuffer.WriteString(\n\t\t\t\tfmt.Sprintf(\"'%s' file content (with size %d bytes) shown below:\\n\",\n\t\t\t\t\ttarHeader.Name, tarHeader.Size,\n\t\t\t\t),\n\t\t\t)\n\t\t}\n\n\t\tconst maxReadFileSize int64 = 100 * 1024 * 1024 // 100 MB limit\n\t\tif tarHeader.Size > maxReadFileSize {\n\t\t\treturn \"\", fmt.Errorf(\"file '%s' size %d exceeds maximum allowed size %d\", tarHeader.Name, tarHeader.Size, maxReadFileSize)","sourceCodeStart":370,"sourceCodeEnd":406,"githubUrl":"https://github.com/vxcontrol/pentagi/blob/ea665308baaff015b226f308438a68d929d0f29b/backend/pkg/tools/terminal.go#L370-L406","documentation":"After CopyFromContainer returns a tar stream, readFileFromContainer iterates it with tar.Reader.Next(). Any decode error that is not io.EOF — meaning the byte stream Docker returned is not a valid/truncated tar archive — is wrapped with this message. It indicates corruption between the daemon and the reader, not a problem with the file itself.","triggerScenarios":"The tar stream from CopyFromContainer was truncated (network hiccup to a remote Docker host, daemon killed mid-response), the reader was closed early, or a non-archive response was produced for special files (device/pipe entries the daemon cannot serialize).","commonSituations":"Reading from a container on a flaky remote Docker host (DOCKER_HOST over TCP/TLS); reading pseudo-files from /proc, /sys, or socket/fifo entries that don't tar cleanly; reading very large files over an unstable connection; a concurrent `docker cp`/container removal interrupted the stream.","solutions":["Retry the read — truncation is often transient; wrap the whole CopyFromContainer+tar loop in a retry with backoff","Avoid tar-reading pseudo-filesystem entries; target regular files (check tarHeader.Typeflag / FileInfo().Mode())","Check the Docker daemon logs and connectivity to the remote host for mid-stream disconnects","If reading large files, read them in chunks or increase client timeouts rather than letting the stream die"],"exampleFix":"// before\n_, err = tarReader.Read(fileContent)\n// after\ntarHeader, err := tarReader.Next()\nif err == io.EOF {\n    break\n}\nif err != nil {\n    if errors.Is(err, io.ErrUnexpectedEOF) {\n        return \"\", fmt.Errorf(\"truncated tar stream from container %s, retry: %w\", containerName, err)\n    }\n    return \"\", fmt.Errorf(\"failed to read tar header: %w\", err)\n}","handlingStrategy":"retry","validationCode":"// No pre-call validation possible; optionally verify daemon connectivity first:\nif _, err := dockerClient.Ping(ctx); err != nil {\n    return fmt.Errorf(\"docker daemon unreachable, fix before reading: %w\", err)\n}","typeGuard":"func isTruncatedTar(err error) bool {\n    return errors.Is(err, io.ErrUnexpectedEOF) || errors.Is(err, tar.ErrHeader)\n}","tryCatchPattern":"var content string\nvar err error\nfor attempt := 0; attempt < 3; attempt++ {\n    content, err = tool.ReadFile(ctx, flowID, path)\n    if err == nil || !strings.Contains(err.Error(), \"failed to read tar header\") {\n        break\n    }\n    time.Sleep(time.Duration(1<<attempt) * 500 * time.Millisecond)\n}","preventionTips":["Use stable local connections or reliable TLS to remote Docker hosts","Avoid tar-reading /proc, /sys, sockets, and FIFOs","Set generous client timeouts for large copies","Retry transient stream errors with exponential backoff"],"tags":["docker","tar","corrupt-stream"],"backgroundTag":"corrupt-tar-archive","analyzedSha":"ea665308baaff015b226f308438a68d929d0f29b","analyzedAt":"2026-09-01T14:16:31.421Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}