multica-ai/multica · error

binary %q not found in archive

Error message

binary %q not found in archive

What it means

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.

Source

Thrown at server/internal/cli/update.go:494

	}

	return fmt.Sprintf("Downloaded %s and replaced %s", assetName, exePath), nil
}

// extractBinaryFromTarGz reads a .tar.gz stream and returns the contents of the
// named file entry.
func extractBinaryFromTarGz(r io.Reader, name string) ([]byte, error) {
	gz, err := gzip.NewReader(r)
	if err != nil {
		return nil, fmt.Errorf("gzip reader: %w", err)
	}
	defer gz.Close()

	tr := tar.NewReader(gz)
	for {
		hdr, err := tr.Next()
		if err == io.EOF {
			return nil, fmt.Errorf("binary %q not found in archive", name)
		}
		if err != nil {
			return nil, fmt.Errorf("read tar: %w", err)
		}
		// Match the binary name (may be prefixed with a directory).
		if filepath.Base(hdr.Name) == name && hdr.Typeflag == tar.TypeReg {
			data, err := io.ReadAll(tr)
			if err != nil {
				return nil, fmt.Errorf("read binary: %w", err)
			}
			return data, nil
		}
	}
}

// extractBinaryFromZip reads a .zip stream and returns the contents of the
// named file entry. The zip format requires random access, so the full archive
// is buffered in memory.

View on GitHub (pinned to 2c0912b6ec)

Solutions

  1. List the archive: `tar -tzf multica_*.tar.gz` and see what the binary is actually named.
  2. Re-release with the binary named 'multica' at the archive root (or nested in any directory — Base matching handles depth, not renaming).
  3. Update the expected binaryName in UpdateViaDownloadWithTimeout to match the shipped name.
  4. Verify the correct GOOS/GOARCH asset was selected by findReleaseAsset for the running machine.

Example fix

null
Defensive patterns

Strategy: validation

Type guard

func isBinaryNotFound(err error) bool {
    return err != nil && strings.HasPrefix(err.Error(), "binary ") && strings.Contains(err.Error(), "not found in archive")
}

Try / catch

data, err := extractBinaryFromTarGz(r, "multica")
if err != nil && isBinaryNotFound(err) {
    // checksum passed but layout changed: list archive, fix name_template, re-release
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of multica-ai/multica@2c0912b6ec (2026-08-15). Data as JSON: /api/errors/39937f353ae16b13. Report an issue: GitHub.