Tencent/WeKnora · error

failed to create Metaso request: %w

Error message

failed to create Metaso request: %w

What it means

Returned by MetasoProvider.Search when http.NewRequestWithContext fails to build the POST request against p.baseURL. This almost always means the baseURL string is not a valid absolute URL (unparseable by url.Parse), so the request can never be sent. It happens at construction time of the request, before any network I/O.

Source

Thrown at internal/infrastructure/web_search/metaso.go:95

		return nil, fmt.Errorf("query is empty")
	}
	if maxResults <= 0 {
		maxResults = defaultMetasoResults
	}
	if maxResults > maxMetasoResults {
		maxResults = maxMetasoResults
	}

	body, err := json.Marshal(metasoSearchRequest{
		Query: query, Scope: p.scope, Size: maxResults,
		IncludeSummary: true, IncludeRawContent: false, ConciseSnippet: true,
	})
	if err != nil {
		return nil, fmt.Errorf("failed to marshal Metaso request: %w", err)
	}
	req, err := http.NewRequestWithContext(ctx, http.MethodPost, p.baseURL, bytes.NewReader(body))
	if err != nil {
		return nil, fmt.Errorf("failed to create Metaso request: %w", err)
	}
	req.Header.Set("Authorization", "Bearer "+p.apiKey)
	req.Header.Set("Accept", "application/json")
	req.Header.Set("Content-Type", "application/json")

	logger.Infof(ctx, "[WebSearch][Metaso] query=%q maxResults=%d scope=%s", query, maxResults, p.scope)
	resp, err := p.client.Do(req)
	if err != nil {
		return nil, fmt.Errorf("failed to execute Metaso request: %w", err)
	}
	defer resp.Body.Close()
	respBody, err := readMetasoResponseBody(resp.Body)
	if err != nil {
		return nil, err
	}
	if resp.StatusCode != http.StatusOK {
		return nil, metasoHTTPError(resp.StatusCode, respBody)
	}

View on GitHub (pinned to 988cbb0330)

Solutions

  1. Print/check p.baseURL and ensure it is a fully qualified URL with scheme, e.g. https://api.metaso.cn/v1/search.
  2. Fix the config/env value supplying the base URL — remove stray whitespace and restore the https:// scheme.
  3. If the base URL is configurable, validate it with url.Parse and require a scheme+host at startup.
  4. If it should be hardcoded, revert to the provider's default constant instead of the overridden value.

Example fix

// before: unvalidated config value
baseURL := os.Getenv("METASO_BASE_URL")
provider, _ := NewMetasoProvider(params) // baseURL empty -> request creation fails

// after: validate and default
baseURL := os.Getenv("METASO_BASE_URL")
if baseURL == "" {
    baseURL = "https://api.metaso.cn/v1/search"
}
if u, err := url.Parse(baseURL); err != nil || u.Scheme == "" || u.Host == "" {
    return nil, fmt.Errorf("invalid METASO_BASE_URL: %q", baseURL)
}
Defensive patterns

Strategy: validation

Validate before calling

func validBaseURL(raw string) error {
    u, err := url.Parse(raw)
    if err != nil || u.Scheme == "" || u.Host == "" {
        return fmt.Errorf("invalid base URL %q: must be absolute with scheme and host", raw)
    }
    return nil
}

// before constructing the provider:
if err := validBaseURL(cfg.MetasoBaseURL); err != nil { return err }

Try / catch

provider, err := NewMetasoProvider(params)
if err != nil {
    if strings.Contains(err.Error(), "failed to create Metaso request") {
        return nil, fmt.Errorf("check Metaso base URL configuration: %w", err)
    }
    return nil, err
}

Prevention

When it happens

Trigger: Search (internal/infrastructure/web_search/metaso.go:95) with a malformed p.baseURL — e.g. empty string, "metaso.cn/api/search" without scheme, or a URL containing control characters/invalid characters.

Common situations: baseURL read from config/env with the scheme stripped; whitespace or newline accidentally included in the configured URL; empty config value defaulting to ""; misconfigured self-hosted proxy URL.

Related errors


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