vxcontrol/pentagi · error · FatalError

internal engine: no link-discovery engine is available

Error message

internal engine: no link-discovery engine is available

What it means

`discoverURLs` iterates over the internal engine's configured link-discovery searchers and calls the first one whose `IsAvailable()` is true. If every entry is nil or unavailable (no search backend configured/keys missing), it returns this Fatal error (backend/pkg/tools/searchers/internal.go:223) — the internal engine cannot even begin because it depends entirely on a link-discovery engine for candidate URLs.

Source

Thrown at backend/pkg/tools/searchers/internal.go:223

// discoverURLs asks the first available link searcher for candidate URLs and extracts
// them from its markdown output. A discovery error is propagated as-is (already typed).
func (e *internalEngine) discoverURLs(ctx context.Context, req Request) ([]string, string, error) {
	linkReq := Request{Query: req.Query, MaxResults: internalLinkDiscoveryLimit}

	for _, l := range e.links {
		if l == nil || !l.IsAvailable() {
			continue
		}
		out, err := l.Handle(ctx, linkReq)
		if err != nil {
			// Propagate the typed error from the link engine; the orchestrator decides
			// retry-vs-fallback for the internal engine as a whole.
			return nil, "", err
		}
		return dedupeURLs(urlPattern.FindAllString(out, -1)), out, nil
	}

	return nil, "", Fatal(fmt.Errorf("internal engine: no link-discovery engine is available"))
}

func (e *internalEngine) buildPrompt(query string, blocks []string) string {
	var sb strings.Builder
	sb.WriteString("<instructions>\n")
	sb.WriteString("TASK: Answer the user query using ONLY the web sources below.\n\n")
	sb.WriteString(fmt.Sprintf("USER QUERY: %q\n\n", query))
	sb.WriteString("REQUIREMENTS:\n")
	sb.WriteString("1. Give a direct, comprehensive answer to the user query.\n")
	sb.WriteString("2. Preserve critical facts, numbers, commands, code snippets, and technical details.\n")
	sb.WriteString("3. Remove any non-essential details that are not relevant to the user query.\n")
	sb.WriteString("4. Cite sources as [Source #] where # is the source id.\n")
	sb.WriteString("5. If the sources do not answer the query, say so explicitly.\n")
	sb.WriteString("6. Use `###` headers to separate paragraphs.\n")
	sb.WriteString("</instructions>\n\n")
	for _, b := range blocks {
		sb.WriteString(b)
		sb.WriteString("\n\n")

View on GitHub (pinned to ea665308ba)

Solutions

  1. Configure at least one link-capable search engine: set its API key/env vars in .env (and docker-compose.yml) and restart
  2. Check Settings UI → search engines and enable one whose Engine() can serve as a link source
  3. Verify the engine is placed in the internal engine's link list in buildSearchEngines (internal.go constructor wiring)
  4. Confirm env vars are actually passed into the backend container (docker compose config) — a missing env var makes IsAvailable() false

Example fix

// before: .env with no search engine
# no search keys
// after
SEARXNG_URL=http://searxng:8080
# or
TAVILY_API_KEY=tvly-...
Defensive patterns

Strategy: validation

Validate before calling

// startup check: at least one link engine available
avail := false
for _, l := range linkEngines {
    if l != nil && l.IsAvailable() { avail = true; break }
}
if !avail {
    return fmt.Errorf("no link-discovery search engine configured; set e.g. SEARXNG_URL or TAVILY_API_KEY")
}

Try / catch

_, err := engine.Handle(ctx, req)
if err != nil && searchers.IsFatal(err) && strings.Contains(err.Error(), "no link-discovery engine") {
    // configuration problem: do not retry, fix env/config
}

Prevention

When it happens

Trigger: `Handle` on the internal engine runs while no link searcher is configured, or all configured ones return `IsAvailable() == false` because their API keys/env vars (e.g. DUCKDUCKGO_*, SEARCHXNG_URL, TAVILY_API_KEY) are unset.

Common situations: Fresh deployment with no search-engine keys in .env; search engine disabled in Settings UI after enabling the internal engine; typo'd env var so availability check fails; `links` slice built empty in buildSearchEngines because all constructors reported not-configured.

Related errors


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