gastownhall/beads · error
failed to create Haiku client: %w
Error message
failed to create Haiku client: %w
What it means
New() builds an Anthropic Haiku client for AI summarization unless DryRun is set. When newHaikuClient fails with an error other than errAPIKeyRequired (which silently downgrades to dry-run), New aborts and wraps the underlying failure. This means the API key was present but the client could not be constructed.
Source
Thrown at internal/compact/compactor.go:71
Concurrency: defaultConcurrency,
}
}
if config.Concurrency <= 0 {
config.Concurrency = defaultConcurrency
}
if apiKey != "" {
config.APIKey = apiKey
}
var haiClient summarizer
var err error
if !config.DryRun {
haiClient, err = newHaikuClient(config.APIKey)
if err != nil {
if errors.Is(err, errAPIKeyRequired) {
config.DryRun = true
} else {
return nil, fmt.Errorf("failed to create Haiku client: %w", err)
}
}
}
if hc, ok := haiClient.(*haikuClient); ok && hc != nil {
hc.auditEnabled = config.AuditEnabled
hc.auditActor = config.Actor
}
return &Compactor{
store: store,
summarizer: haiClient,
config: config,
}, nil
}
// CompactTier1 compacts a single issue at Tier 1 (basic summarization).
func (c *Compactor) CompactTier1(ctx context.Context, issueID string) error {
if ctx.Err() != nil {View on GitHub (pinned to 71377f2769)
Solutions
- Set DryRun: true in the Config (or pass an empty apiKey) if you do not intend to use the real AI path
- Inspect the wrapped error (%w) to find the root cause from newHaikuClient and fix the API key value
- Validate the API key format/credentials before calling compact.New
- In tests, always pass DryRun: true unless the test explicitly exercises the API path
Example fix
// before
c, err := compact.New(store, os.Getenv("ANTHROPIC_API_KEY"), nil)
// after
key := strings.TrimSpace(os.Getenv("ANTHROPIC_API_KEY"))
cfg := &compact.Config{DryRun: key == ""}
c, err := compact.New(store, key, cfg) Defensive patterns
Strategy: validation
Validate before calling
key := strings.TrimSpace(os.Getenv("ANTHROPIC_API_KEY"))
if key == "" {
cfg.DryRun = true // missing key downgrades to dry-run, not an error
} else if len(key) < 20 || !strings.HasPrefix(key, "sk-") {
return fmt.Errorf("ANTHROPIC_API_KEY looks malformed")
} Try / catch
c, err := compact.New(store, key, cfg)
if err != nil {
var retryable bool
if !strings.Contains(err.Error(), "API key") { retryable = true }
return fmt.Errorf("compactor init: %w (retryable=%v)", err, retryable)
} Prevention
- Always set DryRun: true in tests and CI without secrets
- Trim and validate the API key before passing it to New
- Remember an empty key silently downgrades to dry-run — log that downgrade
- Check New's error immediately instead of using a possibly-nil Compactor
When it happens
Trigger: Calling compact.New(store, apiKey, &compact.Config{DryRun:false, ...}) with a non-empty API key that newHaikuClient rejects for reasons other than being missing (e.g. malformed/invalid key format, client construction failure).
Common situations: API key pasted with whitespace/newline or wrong env var containing a garbage value; an Anthropic SDK client constructor failing on bad configuration; tests constructing a real client unintentionally because DryRun was left false and a stub key was supplied.
Related errors
- dolt directory is required
- invalid database name: %q; hyphens are not allowed in embedd
- embeddeddolt: invalid database name: %q; hyphens are not all
- failed to open database: %w Hint: %s
- failed to load %s: %w; no storage database was opened or mod
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/aef7a8e5e1e373ea.
Report an issue: GitHub.