{"record":{"id":"c33e0f9257cf9c24","repo":"github/copilot-sdk","slug":"failed-to-extract-binary-copy-error-v-close-er","errorCode":null,"errorMessage":"failed to extract binary (copy error: %v, close error: %v)","messagePattern":"failed to extract binary \\(copy error: (.+?), close error: (.+?)\\)","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"go/cmd/bundler/main.go","lineNumber":1183,"sourceCode":"\tfor {\n\t\theader, 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: %w\", err)\n\t\t}\n\n\t\tif header.Name == targetPath {\n\t\t\toutPath := filepath.Join(destDir, outputName)\n\t\t\toutFile, err := os.OpenFile(outPath, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, os.FileMode(header.Mode))\n\t\t\tif err != nil {\n\t\t\t\treturn fmt.Errorf(\"failed to create output file: %w\", err)\n\t\t\t}\n\n\t\t\tif _, err := io.Copy(outFile, tarReader); err != nil {\n\t\t\t\tif cerr := outFile.Close(); cerr != nil {\n\t\t\t\t\treturn fmt.Errorf(\"failed to extract binary (copy error: %v, close error: %v)\", err, cerr)\n\t\t\t\t}\n\t\t\t\treturn fmt.Errorf(\"failed to extract binary: %w\", err)\n\t\t\t}\n\t\t\tif err := outFile.Close(); err != nil {\n\t\t\t\treturn fmt.Errorf(\"failed to close output file: %w\", err)\n\t\t\t}\n\t\t\treturn nil\n\t\t}\n\t}\n\n\treturn fmt.Errorf(\"file %q not found in tarball\", targetPath)\n}\n\n// extractOptionalFileFromTarball extracts a single file from a .tgz into destDir\n// like extractFileFromTarball, but returns (false, nil) instead of an error when\n// the file is absent. Used for the runtime library, which older CLI packages do\n// not ship.\nfunc extractOptionalFileFromTarball(tarballPath, destDir, targetPath, outputName string) (bool, error) {","sourceCodeStart":1165,"sourceCodeEnd":1201,"githubUrl":"https://github.com/github/copilot-sdk/blob/cd8cf15dc3f9e762615790aaed0a771a0f392755/go/cmd/bundler/main.go#L1165-L1201","documentation":"While copying the matched tar entry into the output file, io.Copy failed and the attempted outFile.Close() also returned an error. Both errors are reported in one message (copy error first, then close error) since the primary root cause must not be masked.","triggerScenarios":"extractFileFromTarball (from buildBundle, downloadCLIBinary, extractOptionalFileFromTarball) hits a corrupt/truncated tar stream mid-entry or a disk-full/read-only write failure, and closing the partially written file also fails.","commonSituations":"Interrupted downloads producing truncated archives; full disk while installing a large CLI binary; failing storage volumes; quota limits on CI runners.","solutions":["Re-download the tarball and verify its checksum","Free disk space or raise quota on the destination volume","Address the close error cause reported in the second half of the message","Retry the extraction on a healthy filesystem"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"if err := verifyChecksum(tarballPath, expectedSHA256); err != nil { return fmt.Errorf(\"corrupt tarball: %w\", err) }\nif free, err := diskFree(destDir); err == nil && free < minRequiredBytes { return fmt.Errorf(\"insufficient disk space\") }","typeGuard":null,"tryCatchPattern":"if err := extractFileFromTarball(tgz, destDir, target, out); err != nil {\n    if strings.Contains(err.Error(), \"copy error\") { log.Printf(\"copy+close failure on %s: %v\", tgz, err) }\n    return err\n}","preventionTips":["Validate checksums before extraction","Reserve sufficient disk space for extracted binaries","Avoid installing onto network volumes in CI","Re-download artifacts rather than retrying corrupt ones"],"tags":["go","io-copy","disk-full","corruption"],"backgroundTag":"file-write-failed","analyzedSha":"cd8cf15dc3f9e762615790aaed0a771a0f392755","analyzedAt":"2026-09-09T18:32:31.973Z","contentChangedAt":"2026-09-09T18:32:31.973Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}