ipfs/kubo · error

could not read versions: %w

Error message

could not read versions: %w

What it means

DistVersions reads the version list for a distribution via a bufio.Scanner and parses each line with semver. If the scanner encounters an I/O or read error mid-scan (scan.Err() != nil), the versions list is incomplete and the read failure is wrapped as "could not read versions". Note it reflects scanner/read failures, not individual unparseable lines (those are skipped with continue).

Source

Thrown at repo/fsrepo/migrations/versions.go:60

func DistVersions(ctx context.Context, fetcher Fetcher, dist string, sortDesc bool) ([]string, error) {
	versionBytes, err := fetcher.Fetch(ctx, path.Join(dist, distVersions))
	if err != nil {
		return nil, err
	}

	prefix := "v"
	var vers []semver.Version

	scan := bufio.NewScanner(bytes.NewReader(versionBytes))
	for scan.Scan() {
		ver, err := semver.Make(strings.TrimLeft(scan.Text(), prefix))
		if err != nil {
			continue
		}
		vers = append(vers, ver)
	}
	if scan.Err() != nil {
		return nil, fmt.Errorf("could not read versions: %w", scan.Err())
	}

	if sortDesc {
		sort.Sort(sort.Reverse(semver.Versions(vers)))
	} else {
		sort.Sort(semver.Versions(vers))
	}

	out := make([]string, len(vers))
	for i := range vers {
		out[i] = prefix + vers[i].String()
	}

	return out, nil
}

View on GitHub (pinned to 329838acdf)

Solutions

  1. Retry the request — the wrapped scan.Err() is usually a transient network failure.
  2. Check connectivity to the distribution endpoint (curl the versions URL) to rule out proxy/firewall blocking.
  3. Inspect the wrapped %w error for the root cause (connection reset, TLS handshake, timeout) and address it.
  4. Configure or wrap the fetcher with sane timeouts/retries before calling DistVersions.
Defensive patterns

Strategy: retry

Try / catch

var vers []string
var err error
for i := 0; i < 3; i++ {
	vers, err = migrations.DistVersions(ctx, fetcher, dist, false)
	if err == nil || !isTransientReadErr(err) {
		break
	}
	select {
	case <-time.After(time.Duration(i+1) * time.Second):
	case <-ctx.Done():
		return ctx.Err()
	}
}
if err != nil {
	return fmt.Errorf("could not read versions: %w", err)
}

Prevention

When it happens

Trigger: Calling DistVersions (directly or via LatestDistVersion / fetchBinary flows) when the underlying reader breaks mid-read: network connection reset while streaming the version file, TLS failure, or an aborted response body from the dist server.

Common situations: Flaky or proxied network connections dropping mid-download, dist server timeouts, firewall/VPN interference, or transient DNS/TLS issues when reaching the distribution endpoint.

Related errors


AI-assisted analysis of ipfs/kubo@329838acdf (2026-09-03). Data as JSON: /api/errors/e0916620572e85a3. Report an issue: GitHub.