charmbracelet/crush · error

agent configuration not found

Error message

agent configuration not found

What it means

Thrown when config exists but cfg.Agents has no entry for config.AgentCoder. The toggle-thinking flow requires the default 'coder' agent to be defined; a config that omits or renames it cannot resolve which model to flip thinking on.

Solutions

  1. Add back the default 'coder' agent definition to your config
  2. Run config validation (crush doctor / startup validation) to catch missing required agents
  3. Update the config to the current schema if it was written by an older Crush version

Example fix

// before (agents without coder)
[agents.task]
model = "anthropic/claude-sonnet-4"
// after
[agents.coder]
model = "anthropic/claude-sonnet-4"
[agents.task]
model = "anthropic/claude-sonnet-4"
Defensive patterns

Strategy: validation

Validate before calling

cfg := m.com.Config()
if cfg == nil || cfg.Agents == nil {
	return // cannot toggle thinking
}
if _, ok := cfg.Agents[config.AgentCoder]; !ok {
	return // coder agent missing
}

Type guard

func coderAgent(cfg *config.Config) (config.AgentConfig, bool) {
	a, ok := cfg.Agents[config.AgentCoder]
	return a, ok
}

Try / catch

agentCfg, ok := cfg.Agents[config.AgentCoder]
if !ok {
	return util.ReportError(fmt.Errorf("toggle thinking: agent %q not configured", config.AgentCoder))()
}

Prevention

When it happens

Trigger: Executing ActionToggleThinking with a config whose Agents map lacks the 'coder' key — e.g. a user-defined agents block that only defines a 'task' agent, or a typo'd/overridden agent name in crushrc.

Common situations: Hand-edited crushrc/crush.json that removed the coder agent; older config versions migrated without the default agent; partial config merges dropping the agent definition.

Related errors


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

Appendix: source

Thrown at internal/ui/model/ui.go:1991

		m.dialog.CloseDialog(dialog.CommandsID)
	case dialog.ActionToggleCompactMode:
		cmds = append(cmds, m.toggleCompactMode())
		m.dialog.CloseDialog(dialog.CommandsID)
	case dialog.ActionTogglePills:
		if cmd := m.togglePillsExpanded(); cmd != nil {
			cmds = append(cmds, cmd)
		}
		m.dialog.CloseDialog(dialog.CommandsID)
	case dialog.ActionToggleThinking:
		cmds = append(cmds, m.updateAgentModelCmd(func() tea.Msg {
			cfg := m.com.Config()
			if cfg == nil {
				return util.ReportError(errors.New("configuration not found"))()
			}

			agentCfg, ok := cfg.Agents[config.AgentCoder]
			if !ok {
				return util.ReportError(errors.New("agent configuration not found"))()
			}

			currentModel := cfg.Models[agentCfg.Model]
			currentModel.Think = !currentModel.Think
			if err := m.com.Workspace.UpdatePreferredModel(config.ScopeGlobal, agentCfg.Model, currentModel); err != nil {
				return util.ReportError(err)()
			}
			m.com.Workspace.UpdateAgentModel(context.TODO())
			status := "disabled"
			if currentModel.Think {
				status = "enabled"
			}
			return util.NewInfoMsg("Thinking mode " + status)
		}))
		m.dialog.CloseDialog(dialog.CommandsID)
	case dialog.ActionToggleTransparentBackground:
		cmds = append(cmds, func() tea.Msg {
			cfg := m.com.Config()

View on GitHub (pinned to 7944b8e522)