Tencent/WeKnora · error

failed to create request: %w

Error message

failed to create request: %w

What it means

http.NewRequestWithContext failed constructing the POST request to the Tavily API endpoint. The request never left the process. Practically this means p.baseURL is not a parseable URL (malformed/whitespace/placeholder text) or the context is already invalid.

Source

Thrown at internal/infrastructure/web_search/tavily.go:80

	if len(query) == 0 {
		return nil, fmt.Errorf("query is empty")
	}
	logger.Infof(ctx, "[WebSearch][Tavily] query=%q maxResults=%d url=%s", query, maxResults, p.baseURL)

	reqBody := tavilySearchRequest{
		APIKey:     p.apiKey,
		Query:      query,
		MaxResults: maxResults,
	}

	bodyBytes, err := json.Marshal(reqBody)
	if err != nil {
		return nil, fmt.Errorf("failed to marshal request: %w", err)
	}

	req, err := http.NewRequestWithContext(ctx, "POST", p.baseURL, bytes.NewReader(bodyBytes))
	if err != nil {
		return nil, fmt.Errorf("failed to create request: %w", err)
	}
	req.Header.Set("Content-Type", "application/json")

	resp, err := p.client.Do(req)
	if err != nil {
		return nil, fmt.Errorf("failed to execute request: %w", err)
	}
	defer resp.Body.Close()

	if resp.StatusCode != http.StatusOK {
		respBody, _ := io.ReadAll(resp.Body)
		logger.Warnf(ctx, "[WebSearch][Tavily] API returned status %d: %s", resp.StatusCode, string(respBody))
		return nil, fmt.Errorf("tavily API returned status %d: %s", resp.StatusCode, string(respBody))
	}

	respBody, err := io.ReadAll(resp.Body)
	if err != nil {
		return nil, fmt.Errorf("failed to read response: %w", err)

View on GitHub (pinned to 988cbb0330)

Solutions

  1. Log the wrapped error and p.baseURL; fix the endpoint value in configuration
  2. url.Parse(p.baseURL) in the constructor/validate step to fail fast with a clearer message
  3. Trim whitespace and expand env placeholders (${VAR}) before storing baseURL
  4. Confirm the context passed to Search is valid and not already canceled

Example fix

// before
baseURL := "${TAVILY_URL}" // unexpanded placeholder
// after
baseURL := os.ExpandEnv(strings.TrimSpace(cfg.TavilyURL))
if _, err := url.Parse(baseURL); err != nil {
    return nil, fmt.Errorf("invalid tavily base URL: %w", err)
}
Defensive patterns

Strategy: validation

Validate before calling

if _, err := url.Parse(baseURL); err != nil {
    return fmt.Errorf("invalid tavily base URL: %w", err)
}

Prevention

When it happens

Trigger: baseURL configured as an invalid URL string (spaces, control characters, "localhost:99999" bad port, unescaped characters) or an unfilled template placeholder; corrupted context value.

Common situations: Config typo in the Tavily endpoint override; env-substitution leaving "${TAVILY_URL}" literal in the config; trailing whitespace/newline from env file parsing.

Related errors


AI-assisted analysis of Tencent/WeKnora@988cbb0330 (2026-09-02). Data as JSON: /api/errors/8d5ff239b928b105. Report an issue: GitHub.