{"record":{"id":"be851d3560cd0a52","repo":"charmbracelet/crush","slug":"default-providers-are-disabled-and-there-are-no-cu","errorCode":null,"errorMessage":"default providers are disabled and there are no custom providers are configured","messagePattern":"default providers are disabled and there are no custom providers are configured","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/config/load.go","lineNumber":514,"sourceCode":"\t\t// Custom-provider headers share the MCP error contract; see\n\t\t// the known-provider loop above.\n\t\tfor k, v := range providerConfig.ExtraHeaders {\n\t\t\tresolved, err := resolver.ResolveValue(v)\n\t\t\tif err != nil {\n\t\t\t\treturn fmt.Errorf(\"resolving provider %s header %q: %w\", id, k, err)\n\t\t\t}\n\t\t\tif resolved == \"\" {\n\t\t\t\tdelete(providerConfig.ExtraHeaders, k)\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tproviderConfig.ExtraHeaders[k] = resolved\n\t\t}\n\n\t\tc.Providers.Set(id, providerConfig)\n\t}\n\n\tif c.Providers.Len() == 0 && c.Options.DisableDefaultProviders {\n\t\treturn fmt.Errorf(\"default providers are disabled and there are no custom providers are configured\")\n\t}\n\n\treturn nil\n}\n\n// applyEnv sets top-level env vars from the config. Keys are sorted for\n// deterministic ordering so that vars referencing other vars via the\n// value resolver produce consistent results.\nfunc (c *Config) applyEnv(resolver VariableResolver) {\n\tkeys := make([]string, 0, len(c.Env))\n\tfor k := range c.Env {\n\t\tkeys = append(keys, k)\n\t}\n\tslices.Sort(keys)\n\tfor _, k := range keys {\n\t\tresolved, err := resolver.ResolveValue(c.Env[k])\n\t\tif err != nil {\n\t\t\tslog.Warn(\"Skipping env var due to resolution failure.\", \"key\", k, \"value\", c.Env[k], \"error\", err)","sourceCodeStart":496,"sourceCodeEnd":532,"githubUrl":"https://github.com/charmbracelet/crush/blob/7944b8e52225d8805e31eacbf7ef24856b0dfb7a/internal/config/load.go#L496-L532","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before (crush.json)\n{\"options\": {\"disable_default_providers\": true}}\n// after\n{\"options\": {\"disable_default_providers\": true}, \"providers\": {\"myllm\": {\"base_url\": \"http://localhost:8080/v1\", \"api_key\": \"x\"}}}","handlingStrategy":"validation","validationCode":"raw, _ := os.ReadFile(\"crush.json\")\nvar c struct {\n    Options  struct{ DisableDefaultProviders bool `json:\"disable_default_providers\"` } `json:\"options\"`\n    Providers map[string]json.RawMessage `json:\"providers\"`\n}\n_ = json.Unmarshal(raw, &c)\nif c.Options.DisableDefaultProviders && len(c.Providers) == 0 {\n    return errors.New(\"disable_default_providers requires at least one custom provider\")\n}","typeGuard":null,"tryCatchPattern":"store, err := config.Load(ctx, opts)\nif err != nil {\n    if strings.Contains(err.Error(), \"default providers are disabled\") {\n        return errors.New(\"add a custom provider or re-enable default providers\")\n    }\n    return err\n}","preventionTips":["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"],"tags":["config","providers","validation"],"backgroundTag":"no-providers-configured","analyzedSha":"7944b8e52225d8805e31eacbf7ef24856b0dfb7a","analyzedAt":"2026-08-29T12:48:59.079Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}