charmbracelet/crush · error

no providers found in the provided source

Error message

no providers found in the provided source

What it means

UpdateProviders requires the resolved provider source to yield at least one provider. If the embedded catalog, fetched URL, or parsed file produces an empty list, it returns this sentinel error rather than caching an empty catalog that would leave the app with no usable providers.

Source

Thrown at internal/config/provider.go:80

	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)
	}

	slog.Info("Providers updated successfully", "count", len(providers), "from", pathOrURL, "to", cachePathFor)
	return nil
}

// resolveHyperAPIKey returns the Hyper API key from the environment or
// the raw config value. The env var takes precedence.
func resolveHyperAPIKey(cfg *Config) string {
	if key := os.Getenv("HYPER_API_KEY"); key != "" {
		return key
	}
	if cfg == nil || cfg.Providers == nil {

View on GitHub (pinned to 7944b8e522)

Solutions

  1. Add at least one provider object to the JSON file or fix the export.
  2. Point at the default catwalk URL or use "embedded" to get the full catalog.
  3. Check the self-hosted catwalk instance for filtering rules that remove all providers.
  4. Run `go test ./internal/config/...` against the embedded snapshot to confirm it is non-empty.

Example fix

// before (providers.json)
[]
// after
[{"id": "anthropic", "name": "Anthropic", "api_endpoint": "https://api.anthropic.com"}]
Defensive patterns

Strategy: validation

Validate before calling

content, _ := os.ReadFile(path)
var providers []catwalk.Provider
if err := json.Unmarshal(content, &providers); err != nil { return err }
if len(providers) == 0 {
    return errors.New("provider file contains an empty list; add at least one provider")
}

Try / catch

if err := config.UpdateProviders(src); err != nil {
    if strings.Contains(err.Error(), "no providers found") {
        slog.Warn("empty source; falling back to embedded catalog")
        err = config.UpdateProviders("embedded")
    }
    return err
}

Prevention

When it happens

Trigger: Calling config.UpdateProviders with a JSON file containing `[]`, or a URL/embedded source that resolves to zero providers.

Common situations: An empty or reset custom provider file; a filtered/misconfigured self-hosted catwalk returning an empty array; accidentally exporting an empty selection.

Related errors


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