{"record":{"id":"6007f776e5966613","repo":"charmbracelet/crush","slug":"no-providers-found-in-the-provided-source","errorCode":null,"errorMessage":"no providers found in the provided source","messagePattern":"no providers found in the provided source","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/config/provider.go","lineNumber":80,"sourceCode":"\tswitch {\n\tcase pathOrURL == \"embedded\":\n\t\tproviders = embedded.GetAll()\n\tcase strings.HasPrefix(pathOrURL, \"http://\") || strings.HasPrefix(pathOrURL, \"https://\"):\n\t\tvar err error\n\t\tproviders, err = catwalk.NewWithURL(pathOrURL).GetProviders(context.Background(), \"\")\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"failed to fetch providers from Catwalk: %w\", err)\n\t\t}\n\tdefault:\n\t\tcontent, err := os.ReadFile(pathOrURL)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"failed to read file: %w\", err)\n\t\t}\n\t\tif err := json.Unmarshal(content, &providers); err != nil {\n\t\t\treturn fmt.Errorf(\"failed to unmarshal provider data: %w\", err)\n\t\t}\n\t\tif len(providers) == 0 {\n\t\t\treturn fmt.Errorf(\"no providers found in the provided source\")\n\t\t}\n\t}\n\n\tif err := newCache[[]catwalk.Provider](cachePathFor(\"providers\")).Store(providers); err != nil {\n\t\treturn fmt.Errorf(\"failed to save providers to cache: %w\", err)\n\t}\n\n\tslog.Info(\"Providers updated successfully\", \"count\", len(providers), \"from\", pathOrURL, \"to\", cachePathFor)\n\treturn nil\n}\n\n// resolveHyperAPIKey returns the Hyper API key from the environment or\n// the raw config value. The env var takes precedence.\nfunc resolveHyperAPIKey(cfg *Config) string {\n\tif key := os.Getenv(\"HYPER_API_KEY\"); key != \"\" {\n\t\treturn key\n\t}\n\tif cfg == nil || cfg.Providers == nil {","sourceCodeStart":62,"sourceCodeEnd":98,"githubUrl":"https://github.com/charmbracelet/crush/blob/7944b8e52225d8805e31eacbf7ef24856b0dfb7a/internal/config/provider.go#L62-L98","documentation":"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.","triggerScenarios":"Calling config.UpdateProviders with a JSON file containing `[]`, or a URL/embedded source that resolves to zero providers.","commonSituations":"An empty or reset custom provider file; a filtered/misconfigured self-hosted catwalk returning an empty array; accidentally exporting an empty selection.","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."],"exampleFix":"// before (providers.json)\n[]\n// after\n[{\"id\": \"anthropic\", \"name\": \"Anthropic\", \"api_endpoint\": \"https://api.anthropic.com\"}]","handlingStrategy":"validation","validationCode":"content, _ := os.ReadFile(path)\nvar providers []catwalk.Provider\nif err := json.Unmarshal(content, &providers); err != nil { return err }\nif len(providers) == 0 {\n    return errors.New(\"provider file contains an empty list; add at least one provider\")\n}","typeGuard":null,"tryCatchPattern":"if err := config.UpdateProviders(src); err != nil {\n    if strings.Contains(err.Error(), \"no providers found\") {\n        slog.Warn(\"empty source; falling back to embedded catalog\")\n        err = config.UpdateProviders(\"embedded\")\n    }\n    return err\n}","preventionTips":["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."],"tags":["providers","validation","empty-data","config"],"backgroundTag":"empty-provider-list","analyzedSha":"7944b8e52225d8805e31eacbf7ef24856b0dfb7a","analyzedAt":"2026-08-29T12:48:59.079Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}