charmbracelet/crush · error

env

Error message

env %q: %w

What it means

This error is returned by resolveEnvs in internal/config/config.go when resolving the `env` map of a provider/LSP/MCP config entry fails. Each value is run through the resolver (which expands shell-style env references like {{ env:VAR }}); if any single entry fails to resolve, the whole resolution aborts and the key name is wrapped into the message. It indicates a bad or unresolvable environment-variable reference in the config, not a bug in Crush.

Solutions

  1. Export the missing environment variable in the shell profile or environment where Crush runs.
  2. Fix the env reference syntax for that key in crushrc/crush.json (check the key name reported in the message).
  3. Replace the env reference with a literal value if dynamic resolution is not needed.
  4. If running under systemd/CI, ensure the variable is passed through to the process environment.

Example fix

// before (crushrc)
provider anthropic
  env ANTHROPIC_API_KEY "{{ env:ANTHROPOIC_API_KEY }}"  # typo: variable unset
end
// after
export ANTHROPIC_API_KEY=sk-...
provider anthropic
  env ANTHROPIC_API_KEY "{{ env:ANTHROPIC_API_KEY }}"
end
Defensive patterns

Strategy: validation

Validate before calling

for k, ref := range providerCfg.Env {
    if err := resolver.ResolveValue(ref); err != nil {
        return fmt.Errorf("env %q is not resolvable: %w", k, err)
    }
}

Type guard

func isResolvableEnvRef(ref string, lookup func(string) (string, bool)) bool {
    for _, name := range extractEnvNames(ref) {
        if _, ok := lookup(name); !ok {
            return false
        }
    }
    return true
}

Try / catch

var out map[string]string
if err := cfg.ResolveEnvs(); err != nil {
    var envErr *EnvResolveError
    if errors.As(err, &envErr) {
        log.Fatalf("set env var %s before starting: %v", envErr.Key, err)
    }
    return err
}

Prevention

When it happens

Trigger: Calling config loading/resolution for a provider, LSP, or MCP entry whose Env map contains a value that r.ResolveValue cannot resolve — typically a reference to an environment variable that is unset, or a malformed reference syntax.

Common situations: A crushrc/crush.json entry references an API key env var (e.g. {{ env:ANTHROPIC_API_KEY }}) that is not exported in the shell or .env file; a typo in the variable name; running Crush from a service/CI environment that lacks the interactive shell's exports.

Understand the failure class

Background: "environment variable is not set" and "Missing keys in environment" errors: what missing required env var messages mean and how to fix them — this error's family across 28 libraries.

Related errors


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

Appendix: source

Thrown at internal/config/config.go:613

// round-trip back to a map at the call site.
//
// See ResolvedArgs for guidance on picking a resolver.
func (l LSPConfig) ResolvedEnv(r VariableResolver) (map[string]string, error) {
	if len(l.Env) == 0 {
		return map[string]string{}, nil
	}
	out := make(map[string]string, len(l.Env))
	// Sort keys so failures are reported deterministically when more
	// than one value would fail.
	keys := make([]string, 0, len(l.Env))
	for k := range l.Env {
		keys = append(keys, k)
	}
	slices.Sort(keys)
	for _, k := range keys {
		v, err := r.ResolveValue(l.Env[k])
		if err != nil {
			return nil, fmt.Errorf("env %q: %w", k, err)
		}
		out[k] = v
	}
	return out, nil
}

type Agent struct {
	ID          string `json:"id,omitempty"`
	Name        string `json:"name,omitempty"`
	Description string `json:"description,omitempty"`
	// This is the id of the system prompt used by the agent
	Disabled bool `json:"disabled,omitempty"`

	Model SelectedModelType `json:"model" jsonschema:"required,description=The model type to use for this agent,enum=large,enum=small,default=large"`

	// The available tools for the agent
	//  if this is nil, all tools are available
	AllowedTools []string `json:"allowed_tools,omitempty"`

View on GitHub (pinned to 7944b8e522)