{"record":{"id":"7be46ba49b841f69","repo":"multica-ai/multica","slug":"read-binary-w","errorCode":null,"errorMessage":"read binary: %w","messagePattern":"read binary: %w","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"server/internal/cli/update.go","lineNumber":503,"sourceCode":"\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"gzip reader: %w\", err)\n\t}\n\tdefer gz.Close()\n\n\ttr := tar.NewReader(gz)\n\tfor {\n\t\thdr, err := tr.Next()\n\t\tif err == io.EOF {\n\t\t\treturn nil, fmt.Errorf(\"binary %q not found in archive\", name)\n\t\t}\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"read tar: %w\", err)\n\t\t}\n\t\t// Match the binary name (may be prefixed with a directory).\n\t\tif filepath.Base(hdr.Name) == name && hdr.Typeflag == tar.TypeReg {\n\t\t\tdata, err := io.ReadAll(tr)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, fmt.Errorf(\"read binary: %w\", err)\n\t\t\t}\n\t\t\treturn data, nil\n\t\t}\n\t}\n}\n\n// extractBinaryFromZip reads a .zip stream and returns the contents of the\n// named file entry. The zip format requires random access, so the full archive\n// is buffered in memory.\nfunc extractBinaryFromZip(r io.Reader, name string) ([]byte, error) {\n\tbuf, err := io.ReadAll(r)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"read zip data: %w\", err)\n\t}\n\n\tzr, err := zip.NewReader(bytes.NewReader(buf), int64(len(buf)))\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"zip reader: %w\", err)","sourceCodeStart":485,"sourceCodeEnd":521,"githubUrl":"https://github.com/multica-ai/multica/blob/2c0912b6ec764b373d44eeea1e80f0d9f11ab417/server/internal/cli/update.go#L485-L521","documentation":"After locating the matching entry, io.ReadAll on the entry body failed; wrapped as 'read binary: %w'. The entry header was found, so this means the member's declared content could not be read — truncation of the final member, or a gzip/flate corruption deep in the stream that only surfaces when the entry bytes are consumed.","triggerScenarios":"The archive ends before the binary member's declared size (truncated upload); flate.CorruptInputError from bit-level corruption that nonetheless matched a stale checksum; storage-level read errors when the archive source is a network body replayed from a buffer.","commonSituations":"Interrupted release uploads; CDN serving partial content with matching content-length edge cases; mirrors re-encoding the stream.","solutions":["Retry the update — transient body corruption typically clears on the next fetch.","Manually extract the asset (tar -xzf) to confirm the member is complete in the published artifact.","If the published asset is truncated, re-run the release upload so the archive and checksums.txt are consistent.","Compare the downloaded asset size with the size listed on the GitHub release page."],"exampleFix":"null","handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"data, err := extractBinaryFromTarGz(r, \"multica\")\nif err != nil && strings.HasPrefix(err.Error(), \"read binary\") {\n    // truncated member: retry the full download; if persistent, re-publish the asset\n}","preventionTips":["Compare downloaded asset size against the release page size after failures","Retry on the poller's next tick before assuming release-side corruption","Re-run uploads that were interrupted to keep checksums consistent"],"tags":["tar","io","truncation","extraction"],"backgroundTag":null,"analyzedSha":"2c0912b6ec764b373d44eeea1e80f0d9f11ab417","analyzedAt":"2026-08-15T13:25:18.241Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}