gastownhall/beads · error · errAPIKeyRequired

%w: set ANTHROPIC_API_KEY, MINIMAX_API_KEY, or ai.api_key in

Error message

%w: set ANTHROPIC_API_KEY, MINIMAX_API_KEY, or ai.api_key in config

What it means

newHaikuClient requires an AI API key to construct the Anthropic (or MiniMax-compatible) client. It resolves the key via config.ResolveAIAPIKey with the order: explicit apiKey parameter > ANTHROPIC_API_KEY env > MINIMAX_API_KEY env > ai.api_key config. If all are empty it returns errAPIKeyRequired wrapped with this message — the compaction feature simply cannot authenticate without a key.

Source

Thrown at internal/compact/haiku.go:51

// haikuClient wraps the Anthropic API for issue summarization.
type haikuClient struct {
	client         anthropic.Client
	model          anthropic.Model
	apiKeySource   config.AIAPIKeySource
	baseURL        string
	tier1Template  *template.Template
	maxRetries     int
	initialBackoff time.Duration
	auditEnabled   bool
	auditActor     string
}

// newHaikuClient creates a new Haiku API client.
// API key resolution order: ANTHROPIC_API_KEY env var > MINIMAX_API_KEY env var > ai.api_key config > explicit apiKey parameter.
func newHaikuClient(apiKey string) (*haikuClient, error) {
	apiKey, keySource := config.ResolveAIAPIKey(apiKey)
	if apiKey == "" {
		return nil, fmt.Errorf("%w: set ANTHROPIC_API_KEY, MINIMAX_API_KEY, or ai.api_key in config", errAPIKeyRequired)
	}

	clientOptions := []option.RequestOption{option.WithAPIKey(apiKey)}
	baseURL := config.DefaultAIBaseURL(keySource)
	if baseURL != "" {
		clientOptions = append(clientOptions, option.WithBaseURL(baseURL))
	}

	client := anthropic.NewClient(clientOptions...)

	tier1Tmpl, err := template.New("tier1").Parse(tier1PromptTemplate)
	if err != nil {
		return nil, fmt.Errorf("failed to parse tier1 template: %w", err)
	}

	aiMetricsOnce.Do(initAIMetrics)

	return &haikuClient{

View on GitHub (pinned to 71377f2769)

Solutions

  1. export ANTHROPIC_API_KEY="sk-ant-..." in your shell or CI environment before running bd
  2. Set MINIMAX_API_KEY instead if you use MiniMax as the provider
  3. Add ai.api_key to the bd config file for a persistent, per-repo setting
  4. Verify resolution order if multiple sources are set — explicit parameter wins, then ANTHROPIC_API_KEY overrides MINIMAX_API_KEY
  5. Check that your service runner (cron/systemd/CI) actually loads the env file

Example fix

// before (key missing)
client, err := compact.New("") // -> errAPIKeyRequired
// after
os.Setenv("ANTHROPIC_API_KEY", os.Getenv("ANTHROPIC_API_KEY")) // ensure exported
client, err := compact.New("") // env var picked up
// or pass explicitly:
client, err := compact.New("sk-ant-...")
Defensive patterns

Strategy: validation

Validate before calling

// check key availability before constructing the client
if os.Getenv("ANTHROPIC_API_KEY") == "" && os.Getenv("MINIMAX_API_KEY") == "" {
	if cfg.AI.APIKey == "" {
		return errors.New("no AI API key: set ANTHROPIC_API_KEY, MINIMAX_API_KEY, or ai.api_key")
	}
}
client, err := compact.New("")

Try / catch

client, err := compact.New(apiKey)
if errors.Is(err, compact.ErrAPIKeyRequired) {
	return fmt.Errorf("configure an AI key: %w", err)
}

Prevention

When it happens

Trigger: Calling New (compact client constructor) when no ANTHROPIC_API_KEY or MINIMAX_API_KEY environment variable is set and ai.api_key is absent/empty in the bd config file.

Common situations: Fresh clone or CI environment where the env var was never exported; running `bd compact` under systemd/cron that does not inherit your shell profile; typos like ANTHROPIC_APIKEY; key defined in the wrong config file; key expired and removed.

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 gastownhall/beads@71377f2769 (2026-08-30). Data as JSON: /api/errors/cc69b2633d2ac5fb. Report an issue: GitHub.