{"record":{"id":"c689b9913051dd3a","repo":"charmbracelet/crush","slug":"env-q-w","errorCode":null,"errorMessage":"env %q: %w","messagePattern":"env %q: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/config/config.go","lineNumber":613,"sourceCode":"// round-trip back to a map at the call site.\n//\n// See ResolvedArgs for guidance on picking a resolver.\nfunc (l LSPConfig) ResolvedEnv(r VariableResolver) (map[string]string, error) {\n\tif len(l.Env) == 0 {\n\t\treturn map[string]string{}, nil\n\t}\n\tout := make(map[string]string, len(l.Env))\n\t// Sort keys so failures are reported deterministically when more\n\t// than one value would fail.\n\tkeys := make([]string, 0, len(l.Env))\n\tfor k := range l.Env {\n\t\tkeys = append(keys, k)\n\t}\n\tslices.Sort(keys)\n\tfor _, k := range keys {\n\t\tv, err := r.ResolveValue(l.Env[k])\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"env %q: %w\", k, err)\n\t\t}\n\t\tout[k] = v\n\t}\n\treturn out, nil\n}\n\ntype Agent struct {\n\tID          string `json:\"id,omitempty\"`\n\tName        string `json:\"name,omitempty\"`\n\tDescription string `json:\"description,omitempty\"`\n\t// This is the id of the system prompt used by the agent\n\tDisabled bool `json:\"disabled,omitempty\"`\n\n\tModel SelectedModelType `json:\"model\" jsonschema:\"required,description=The model type to use for this agent,enum=large,enum=small,default=large\"`\n\n\t// The available tools for the agent\n\t//  if this is nil, all tools are available\n\tAllowedTools []string `json:\"allowed_tools,omitempty\"`","sourceCodeStart":595,"sourceCodeEnd":631,"githubUrl":"https://github.com/charmbracelet/crush/blob/7944b8e52225d8805e31eacbf7ef24856b0dfb7a/internal/config/config.go#L595-L631","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Export the missing environment variable in the shell profile or environment where Crush runs.","Fix the env reference syntax for that key in crushrc/crush.json (check the key name reported in the message).","Replace the env reference with a literal value if dynamic resolution is not needed.","If running under systemd/CI, ensure the variable is passed through to the process environment."],"exampleFix":"// before (crushrc)\nprovider anthropic\n  env ANTHROPIC_API_KEY \"{{ env:ANTHROPOIC_API_KEY }}\"  # typo: variable unset\nend\n// after\nexport ANTHROPIC_API_KEY=sk-...\nprovider anthropic\n  env ANTHROPIC_API_KEY \"{{ env:ANTHROPIC_API_KEY }}\"\nend","handlingStrategy":"validation","validationCode":"for k, ref := range providerCfg.Env {\n    if err := resolver.ResolveValue(ref); err != nil {\n        return fmt.Errorf(\"env %q is not resolvable: %w\", k, err)\n    }\n}","typeGuard":"func isResolvableEnvRef(ref string, lookup func(string) (string, bool)) bool {\n    for _, name := range extractEnvNames(ref) {\n        if _, ok := lookup(name); !ok {\n            return false\n        }\n    }\n    return true\n}","tryCatchPattern":"var out map[string]string\nif err := cfg.ResolveEnvs(); err != nil {\n    var envErr *EnvResolveError\n    if errors.As(err, &envErr) {\n        log.Fatalf(\"set env var %s before starting: %v\", envErr.Key, err)\n    }\n    return err\n}","preventionTips":["Document required env vars in the repo and assert them at startup.","Use direnv or a checked-in .env.example to keep variable names consistent.","Prefer literal config values over env references for non-secret settings."],"tags":["config","environment-variables","resolution"],"backgroundTag":"missing-env-var","analyzedSha":"7944b8e52225d8805e31eacbf7ef24856b0dfb7a","analyzedAt":"2026-08-29T12:48:59.079Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}