charmbracelet/crush · error
default providers are disabled and there are no custom provi
Error message
default providers are disabled and there are no custom providers are configured
What it means
configureProviders explicitly rejects a configuration where default (catalog) providers are disabled but zero custom providers were defined — the app would have no way to talk to any LLM. The error is returned verbatim without wrapping the cause.
Source
Thrown at internal/config/load.go:514
// Custom-provider headers share the MCP error contract; see
// the known-provider loop above.
for k, v := range providerConfig.ExtraHeaders {
resolved, err := resolver.ResolveValue(v)
if err != nil {
return fmt.Errorf("resolving provider %s header %q: %w", id, k, err)
}
if resolved == "" {
delete(providerConfig.ExtraHeaders, k)
continue
}
providerConfig.ExtraHeaders[k] = resolved
}
c.Providers.Set(id, providerConfig)
}
if c.Providers.Len() == 0 && c.Options.DisableDefaultProviders {
return fmt.Errorf("default providers are disabled and there are no custom providers are configured")
}
return nil
}
// applyEnv sets top-level env vars from the config. Keys are sorted for
// deterministic ordering so that vars referencing other vars via the
// value resolver produce consistent results.
func (c *Config) applyEnv(resolver VariableResolver) {
keys := make([]string, 0, len(c.Env))
for k := range c.Env {
keys = append(keys, k)
}
slices.Sort(keys)
for _, k := range keys {
resolved, err := resolver.ResolveValue(c.Env[k])
if err != nil {
slog.Warn("Skipping env var due to resolution failure.", "key", k, "value", c.Env[k], "error", err)View on GitHub (pinned to 7944b8e522)
Solutions
- Add at least one custom provider under the providers section
- Or remove/disable the disable_default_providers option to use catalog providers
- Verify the providers section wasn't lost in a merge or placed in the wrong scope/file
- Check that provider IDs don't collide/overwrite each other leaving the map empty
Example fix
// before (crush.json)
{"options": {"disable_default_providers": true}}
// after
{"options": {"disable_default_providers": true}, "providers": {"myllm": {"base_url": "http://localhost:8080/v1", "api_key": "x"}}} Defensive patterns
Strategy: validation
Validate before calling
raw, _ := os.ReadFile("crush.json")
var c struct {
Options struct{ DisableDefaultProviders bool `json:"disable_default_providers"` } `json:"options"`
Providers map[string]json.RawMessage `json:"providers"`
}
_ = json.Unmarshal(raw, &c)
if c.Options.DisableDefaultProviders && len(c.Providers) == 0 {
return errors.New("disable_default_providers requires at least one custom provider")
} Try / catch
store, err := config.Load(ctx, opts)
if err != nil {
if strings.Contains(err.Error(), "default providers are disabled") {
return errors.New("add a custom provider or re-enable default providers")
}
return err
} Prevention
- Only set disable_default_providers when a custom provider is fully defined
- Verify the providers section exists and is non-empty after merges
- Keep disable flag and custom providers in the same file to keep them in sync
- Lint config for this invariant in CI
When it happens
Trigger: c.Providers.Len() == 0 && c.Options.DisableDefaultProviders is true at the end of configureProviders — i.e. options.disable_default_providers is set (true) while the providers map is empty.
Common situations: User set disable_default_providers: true intending to use only custom providers but forgot to define one; a merge dropped the custom providers section; copying a minimal config snippet that disables defaults.
Related errors
- no providers found in the provided source
- 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/be851d3560cd0a52.
Report an issue: GitHub.