vxcontrol/pentagi · error

failed to get searcher handler: %w

Error message

failed to get searcher handler: %w

What it means

PerformAgentChain wraps the error from fp.GetSubtaskSearcherHandler(ctx, nil, nil), which builds the subtask searcher tool handler. This is the last handler constructed before the observation/agent loop starts; failure aborts the chain setup.

Source

Thrown at backend/pkg/providers/assistant.go:195

		return fmt.Errorf("failed to get installer handler: %w", err)
	}

	memorist, err := ap.fp.GetMemoristHandler(ctx, nil, nil)
	if err != nil {
		logger.WithError(err).Error("failed to get memorist handler")
		return fmt.Errorf("failed to get memorist handler: %w", err)
	}

	pentester, err := ap.fp.GetPentesterHandler(ctx, nil, nil)
	if err != nil {
		logger.WithError(err).Error("failed to get pentester handler")
		return fmt.Errorf("failed to get pentester handler: %w", err)
	}

	searcher, err := ap.fp.GetSubtaskSearcherHandler(ctx, nil, nil)
	if err != nil {
		logger.WithError(err).Error("failed to get searcher handler")
		return fmt.Errorf("failed to get searcher handler: %w", err)
	}

	ctx, observation := obs.Observer.NewObservation(ctx)
	executorAgent := observation.Agent(
		langfuse.WithAgentName(fmt.Sprintf("assistant %d for flow %d: %s", ap.id, ap.fp.ID(), ap.fp.Title())),
		langfuse.WithAgentInput(chain),
		langfuse.WithAgentMetadata(langfuse.Metadata{
			"assistant_id": ap.id,
			"flow_id":      ap.fp.ID(),
			"msg_chain_id": ap.msgChainID,
			"provider":     ap.fp.Type(),
			"image":        ap.fp.Image(),
			"lang":         ap.fp.Language(),
		}),
	)
	ctx, _ = executorAgent.Observation(ctx)

	cfg := tools.AssistantExecutorConfig{

View on GitHub (pinned to ea665308ba)

Solutions

  1. Set at least one search engine config in .env (e.g. TAVILY_API_KEY or GOOGLE keys) and restart the backend.
  2. Verify outbound network/DNS from the backend container.
  3. Check the wrapped error in logs to identify the failing searcher.
  4. Cross-check env var names against .env.example after upgrading.

Example fix

// before
searcher, err := ap.fp.GetSubtaskSearcherHandler(ctx, nil, nil)
if err != nil {
    return fmt.Errorf("failed to get searcher handler: %w", err)
}
// after
searcher, err := ap.fp.GetSubtaskSearcherHandler(ctx, &taskID, &subtaskID)
if err != nil {
    logger.WithError(err).Error("searcher init failed — configure at least one search engine")
    return fmt.Errorf("failed to get searcher handler: %w", err)
}
Defensive patterns

Strategy: try-catch

Validate before calling

engines := 0
for _, k := range []string{"GOOGLE_API_KEY", "TAVILY_API_KEY", "SEARXNG_URL", "PERPLEXITY_API_KEY"} {
    if os.Getenv(k) != "" { engines++ }
}
if engines == 0 { return errors.New("configure at least one search engine before running flows") }

Try / catch

searcher, err := ap.fp.GetSubtaskSearcherHandler(ctx, nil, nil)
if err != nil {
    logger.WithError(err).Error("searcher handler init failed")
    return fmt.Errorf("failed to get searcher handler: %w", err)
}

Prevention

When it happens

Trigger: Searcher handler factory fails: no search engine configured/available, web-search tool config missing, or dependent lookups error.

Common situations: No search provider keys in .env (DuckDuckGo unconfigured and paid engines missing); SEARCH_* env vars renamed after an upgrade; outbound network blocked so availability checks fail.

Related errors


AI-assisted analysis of vxcontrol/pentagi@ea665308ba (2026-09-01). Data as JSON: /api/errors/b5b6d49a6f3d70e1. Report an issue: GitHub.