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
- Add at least one provider object to the JSON file or fix the export.
- Point at the default catwalk URL or use "embedded" to get the full catalog.
- Check the self-hosted catwalk instance for filtering rules that remove all providers.
- 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
- Never commit an empty `[]` provider file; validate contents before shipping.
- Verify custom catwalk instances return a non-empty array (curl + jq 'length').
- Fall back to the "embedded" source when a custom source yields zero providers.
- Add a startup assertion that Providers() is non-empty after update.
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
- default providers are disabled and there are no custom provi
- not a valid bedrock api key
- not a valid vercel api key
- mcp stdio config requires a non-empty 'command' field
- mcp http config requires a non-empty 'url' field
AI-assisted analysis of charmbracelet/crush@7944b8e522 (2026-08-29).
Data as JSON: /api/errors/6007f776e5966613.
Report an issue: GitHub.