Tencent/WeKnora · error

failed to marshal Metaso request: %w

Error message

failed to marshal Metaso request: %w

What it means

Returned by MetasoProvider.Search when json.Marshal of the metasoSearchRequest struct fails before any HTTP call is made. With a fixed struct of string/int/bool fields this should practically never happen (encoding/json only errors on unsupported types like channels or cyclic values), so encountering it indicates corrupted or non-serializable data injected into the request struct. The marshal error is wrapped via %w.

Source

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

func (p *MetasoProvider) Search(ctx context.Context, query string, maxResults int, includeDate bool) ([]*types.WebSearchResult, error) {
	query = strings.TrimSpace(query)
	if query == "" {
		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

View on GitHub (pinned to 988cbb0330)

Solutions

  1. Inspect the wrapped error (%w) to see which value json.Marshal rejected.
  2. Sanitize the query: strip or replace invalid UTF-8 (e.g. strings.ToValidUTF8(query, "\uFFFD")).
  3. Review any local modifications to metasoSearchRequest for fields json cannot encode (func, chan, cycle).
  4. If using a custom MarshalJSON, fix it to return valid JSON or nil error.

Example fix

// before: pass raw input straight through
results, err := provider.Search(ctx, rawInput, 10, false)

// after: ensure valid UTF-8
clean := strings.ToValidUTF8(strings.TrimSpace(rawInput), "\uFFFD")
results, err := provider.Search(ctx, clean, 10, false)
Defensive patterns

Strategy: validation

Validate before calling

if !utf8.ValidString(query) {
    query = strings.ToValidUTF8(query, "\uFFFD")
}
if query == "" {
    return fmt.Errorf("query must be non-empty UTF-8 text")
}

Try / catch

results, err := provider.Search(ctx, query, 10, false)
if err != nil {
    var jsonErr *json.UnsupportedTypeError
    if errors.As(err, &jsonErr) {
        return nil, fmt.Errorf("request serialization bug: %w", err)
    }
    return nil, err
}

Prevention

When it happens

Trigger: Search (internal/infrastructure/web_search/metaso.go:91) calls json.Marshal(metasoSearchRequest{...}) and it returns an error — realistically only if a field carries an unsupported value, e.g. query containing invalid UTF-8 that a custom MarshalJSON rejects, or the struct being modified to hold non-serializable types.

Common situations: Query string containing invalid UTF-8 bytes from binary input; a fork/customization that added a func or chan field to metasoSearchRequest; a custom MarshalJSON implementation returning an error.

Understand the failure class

Background: json.Marshal / "failed to marshal" errors in Go: why "unsupported type" happens and how to fix it — this error's family across 22 libraries.

Related errors


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