{"record":{"id":"39937f353ae16b13","repo":"multica-ai/multica","slug":"binary-q-not-found-in-archive","errorCode":null,"errorMessage":"binary %q not found in archive","messagePattern":"binary %q not found in archive","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"server/internal/cli/update.go","lineNumber":494,"sourceCode":"\t}\n\n\treturn fmt.Sprintf(\"Downloaded %s and replaced %s\", assetName, exePath), nil\n}\n\n// extractBinaryFromTarGz reads a .tar.gz stream and returns the contents of the\n// named file entry.\nfunc extractBinaryFromTarGz(r io.Reader, name string) ([]byte, error) {\n\tgz, err := gzip.NewReader(r)\n\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.","sourceCodeStart":476,"sourceCodeEnd":512,"githubUrl":"https://github.com/multica-ai/multica/blob/2c0912b6ec764b373d44eeea1e80f0d9f11ab417/server/internal/cli/update.go#L476-L512","documentation":"extractBinaryFromTarGz iterated to io.EOF without finding a regular entry whose filepath.Base(name) equals the requested binary name; it returns 'binary %q not found in archive'. The archive itself was valid (checksum-verified) — its contents just do not contain 'multica' as a regular file at any directory depth.","triggerScenarios":"The inner binary was renamed in the release config (e.g. to multica-server or a versioned name); the archive contains only a top-level directory with a different binary name; a non-Windows release accidentally packaged with the Windows name (multica.exe) so the Unix lookup misses.","commonSituations":"GoReleaser builds.name_template changed after shipping the updater; forks renaming the binary; releases that bundle multiple binaries where the expected one is absent for a platform.","solutions":["List the archive: `tar -tzf multica_*.tar.gz` and see what the binary is actually named.","Re-release with the binary named 'multica' at the archive root (or nested in any directory — Base matching handles depth, not renaming).","Update the expected binaryName in UpdateViaDownloadWithTimeout to match the shipped name.","Verify the correct GOOS/GOARCH asset was selected by findReleaseAsset for the running machine."],"exampleFix":"null","handlingStrategy":"validation","validationCode":null,"typeGuard":"func isBinaryNotFound(err error) bool {\n    return err != nil && strings.HasPrefix(err.Error(), \"binary \") && strings.Contains(err.Error(), \"not found in archive\")\n}","tryCatchPattern":"data, err := extractBinaryFromTarGz(r, \"multica\")\nif err != nil && isBinaryNotFound(err) {\n    // checksum passed but layout changed: list archive, fix name_template, re-release\n}","preventionTips":["Keep the inner binary named 'multica' (or 'multica.exe') in release archives","Verify archive contents in release CI with tar -tzf / unzip -l","Note that matching uses filepath.Base, so subdirectories are fine but renames are not"],"tags":["archive","tar","packaging","release"],"backgroundTag":null,"analyzedSha":"2c0912b6ec764b373d44eeea1e80f0d9f11ab417","analyzedAt":"2026-08-15T13:25:18.241Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}