multica-ai/multica · error
fetch release metadata: %w
Error message
fetch release metadata: %w
What it means
fetchReleaseByTag queries the GitHub releases API for the normalized tag; failure is wrapped as 'fetch release metadata: %w'. This is the first network hop of the download-based updater, so network errors, GitHub rate limits (HTTP 403 with an API error body), 404 for a nonexistent tag, and timeouts all appear here.
Source
Thrown at server/internal/cli/update.go:385
return UpdateViaDownloadWithTimeout(targetVersion, DefaultUpdateDownloadTimeout)
}
// UpdateViaDownloadWithTimeout downloads the latest release binary with a caller-selected timeout.
func UpdateViaDownloadWithTimeout(targetVersion string, downloadTimeout time.Duration) (string, error) {
// Determine current binary path.
exePath, err := selfexec.Resolve()
if err != nil {
return "", fmt.Errorf("resolve executable path: %w", err)
}
exePath, err = filepath.EvalSymlinks(exePath)
if err != nil {
return "", fmt.Errorf("resolve symlink: %w", err)
}
tag := normalizeReleaseTag(targetVersion)
release, err := fetchReleaseByTag(tag)
if err != nil {
return "", fmt.Errorf("fetch release metadata: %w", err)
}
asset, err := findReleaseAsset(release.Assets, tag, runtime.GOOS, runtime.GOARCH)
if err != nil {
return "", err
}
manifestAsset, err := findChecksumManifestAsset(release.Assets)
if err != nil {
return "", err
}
downloadURL := asset.BrowserDownloadURL
assetName := asset.Name
// Pull the checksum manifest first so a release that is half-published
// (archives uploaded but checksums.txt not yet) fails before we eat the
// archive's bandwidth.
timeout := updateDownloadTimeoutOrDefault(downloadTimeout)
manifestData, err := fetchURLBytes(manifestAsset.BrowserDownloadURL, timeout)
if err != nil {View on GitHub (pinned to 2c0912b6ec)
Solutions
- Confirm the tag exists: `gh release view <tag>` or open https://github.com/multica-ai/multica/releases/tag/<tag>.
- For rate limiting, add an Authorization header/token to the API request or reduce poll frequency.
- For network failures, verify connectivity to api.github.com and retry — the poller retries on its next tick.
- Pass an empty targetVersion only if the code path supports fetching latest; otherwise use a real released tag.
Example fix
null
Defensive patterns
Strategy: retry
Type guard
func isGitHubAPIError(err error) bool {
return err != nil && strings.Contains(err.Error(), "fetch release metadata")
} Try / catch
out, err := cli.UpdateViaDownload(ver)
if err != nil && isGitHubAPIError(err) {
// network/rate-limit: retry on the next poll tick with backoff
return retryLater(err)
} Prevention
- Verify the tag exists before targeting it
- Authenticate GitHub API calls in fleet deployments to raise rate limits
- Space update polls minutes apart, not seconds
When it happens
Trigger: Calling UpdateViaDownload with a version whose tag does not exist on GitHub; unauthenticated API access beyond 60 req/h per IP; DNS/proxy failure; the API returning a non-200 that fetchReleaseByTag converts to an error.
Common situations: Fleets of machines polling for updates from one IP hitting the rate limit; corporate proxies blocking api.github.com; a typo'd or unpushed targetVersion passed from config.
Related errors
- import source temporarily unavailable
- create agent: %w
- update agent: %w
- list agent tasks: %w
- list agent skills: %w
AI-assisted analysis of multica-ai/multica@2c0912b6ec (2026-08-15).
Data as JSON: /api/errors/ea3c6dfe721d333b.
Report an issue: GitHub.