sipeed/picoclaw · error

no API key provided

Error message

no API key provided

What it means

BraveSearchProvider.Search refuses to run when its APIKeyPool is nil or has zero keys. The pool is built by NewAPIKeyPool(keys) from configured Brave API keys; in the standard WebTool wiring, providers without credentials are not registered at all, so hitting this usually means direct provider construction or a config race.

Source

Thrown at pkg/tools/integration/web.go:285

		return nil
	}
	return lens
}

type BraveSearchProvider struct {
	keyPool *APIKeyPool
	proxy   string
	client  *http.Client
}

func (p *BraveSearchProvider) Search(
	ctx context.Context,
	query string,
	count int,
	rangeCode string,
) (string, error) {
	if p.keyPool == nil || len(p.keyPool.keys) == 0 {
		return "", errors.New("no API key provided")
	}

	searchURL := fmt.Sprintf("https://api.search.brave.com/res/v1/web/search?q=%s&count=%d",
		url.QueryEscape(query), count)
	if freshness := mapBraveFreshness(rangeCode); freshness != "" {
		searchURL += "&freshness=" + url.QueryEscape(freshness)
	}

	var lastErr error
	iter := p.keyPool.NewIterator()

	for {
		apiKey, ok := iter.Next()
		if !ok {
			break
		}

		req, err := http.NewRequestWithContext(ctx, "GET", searchURL, nil)

View on GitHub (pinned to 49183d7e8d)

Solutions

  1. Configure the Brave API key(s) for the web search provider in picoclaw config (or the env var your deployment reads them from) and restart
  2. Verify the key list actually reaches the provider: len(pool.Keys) > 0 before serving
  3. If no Brave key is available, switch the provider to one with credentials or to SearXNG (needs only a URL)

Example fix

// before
p := &integration.BraveSearchProvider{} // no keyPool

// after
pool := integration.NewAPIKeyPool([]string{os.Getenv("BRAVE_API_KEY")})
p := &integration.BraveSearchProvider{KeyPool: pool}
Defensive patterns

Strategy: validation

Validate before calling

keys := []string{os.Getenv("BRAVE_API_KEY")}
keys = slices.DeleteFunc(keys, func(k string) bool { return strings.TrimSpace(k) == "" })
if len(keys) == 0 {
    return errors.New("brave selected but no API key configured")
}
p := &integration.BraveSearchProvider{KeyPool: integration.NewAPIKeyPool(keys)}

Try / catch

result, err := provider.Search(ctx, q, n, rangeCode)
if err != nil {
    if err.Error() == "no API key provided" {
        // config problem: disable brave or load keys, do not retry
    }
    return err
}

Prevention

When it happens

Trigger: Calling Search on a BraveSearchProvider constructed with an empty key list (NewAPIKeyPool(nil) / NewAPIKeyPool([]string{})), i.e. brave is selected but no API key made it into the provider.

Common situations: Brave set as the web-search provider in picoclaw config without its API key(s); key env var not exported in the service unit; multiple keys configured as a single comma string instead of a list so parsing yields nothing.

Related errors


AI-assisted analysis of sipeed/picoclaw@49183d7e8d (2026-08-15). Data as JSON: /api/errors/6e3e47a39a5f575c. Report an issue: GitHub.