charmbracelet/crush · error

failed to fetch providers from Catwalk: %w

Error message

failed to fetch providers from Catwalk: %w

What it means

UpdateProviders resolves the provider catalog from a source: the embedded snapshot, an http(s) URL fetched via catwalk, or a local JSON file. This error is returned when the catwalk HTTP client fails to GET the providers endpoint at the given URL, wrapping the network/HTTP error. It means no provider list could be downloaded, so the config cannot resolve providers/models.

Source

Thrown at internal/config/provider.go:69

		return filepath.Join(localAppData, appName, name+".json")
	}

	return filepath.Join(home.Dir(), ".local", "share", appName, name+".json")
}

// UpdateProviders updates the Catwalk providers list from a specified source.
func UpdateProviders(pathOrURL string) error {
	var providers []catwalk.Provider
	pathOrURL = cmp.Or(pathOrURL, os.Getenv("CATWALK_URL"), defaultCatwalkURL)

	switch {
	case pathOrURL == "embedded":
		providers = embedded.GetAll()
	case strings.HasPrefix(pathOrURL, "http://") || strings.HasPrefix(pathOrURL, "https://"):
		var err error
		providers, err = catwalk.NewWithURL(pathOrURL).GetProviders(context.Background(), "")
		if err != nil {
			return fmt.Errorf("failed to fetch providers from Catwalk: %w", err)
		}
	default:
		content, err := os.ReadFile(pathOrURL)
		if err != nil {
			return fmt.Errorf("failed to read file: %w", err)
		}
		if err := json.Unmarshal(content, &providers); err != nil {
			return fmt.Errorf("failed to unmarshal provider data: %w", err)
		}
		if len(providers) == 0 {
			return fmt.Errorf("no providers found in the provided source")
		}
	}

	if err := newCache[[]catwalk.Provider](cachePathFor("providers")).Store(providers); err != nil {
		return fmt.Errorf("failed to save providers to cache: %w", err)
	}

View on GitHub (pinned to 7944b8e522)

Solutions

  1. Check network reachability: `curl -v <url>` to reproduce the underlying error shown after %w.
  2. Fix the URL (scheme, host, port) in the config or CLI flag.
  3. Set HTTP proxy env vars (HTTPS_PROXY) if behind a corporate proxy.
  4. Use a local JSON file path or the "embedded" source as a fallback and retry later.

Example fix

// before
err := config.UpdateProviders("https://catwalk.internal.example:9000")
// after
if err := config.UpdateProviders("https://catwalk.internal.example:9000"); err != nil {
    slog.Warn("falling back to embedded providers", "err", err)
    err = config.UpdateProviders("embedded")
}
Defensive patterns

Strategy: try-catch

Validate before calling

u, err := url.Parse(src)
if err != nil || (u.Scheme != "http" && u.Scheme != "https") { /* validate URL before use */ }
resp, err := http.Head(u.String())
if err != nil || resp.StatusCode >= 500 { /* surface connectivity problem before UpdateProviders */ }

Try / catch

providers, err := fetchFromCatwalk(ctx, url)
if err != nil {
    var netErr net.Error
    switch {
    case errors.As(err, &netErr):
        slog.Warn("catwalk unreachable, retrying with backoff", "err", err)
    case errors.Is(err, context.DeadlineExceeded):
        slog.Warn("catwalk fetch timed out")
    }
    return err
}

Prevention

When it happens

Trigger: Calling config.UpdateProviders with a pathOrURL starting with http:// or https:// when the Catwalk server is unreachable, returns 5xx, DNS fails, TLS fails, or the request context is cancelled.

Common situations: Pointing the provider source at a self-hosted catwalk instance with a wrong port or hostname; offline/behind a corporate proxy; the catwalk service being down during `crush update-providers` or app startup with autoupdate enabled.

Understand the failure class

Background: 'Something went wrong' / 'Request failed (500)' / 'HTTP error! status: 404' — what failed HTTP requests actually mean and how to find the real cause — this error's family across 28 libraries.

Related errors


AI-assisted analysis of charmbracelet/crush@7944b8e522 (2026-08-29). Data as JSON: /api/errors/0daed9d281b6efec. Report an issue: GitHub.