Tencent/WeKnora · error
failed to unmarshal response: %w
Error message
failed to unmarshal response: %w
What it means
json.Unmarshal could not decode the Bing response body into bingSearchResponse, so doSearch wraps the underlying error with this message. It means the body is not valid JSON or its shape doesn't match the expected struct.
Source
Thrown at internal/infrastructure/web_search/bing.go:116
resp, err := p.client.Do(req)
if err != nil {
return nil, err
}
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
if err != nil {
return nil, err
}
if resp.StatusCode != http.StatusOK {
logger.Warnf(ctx, "[WebSearch][Bing] API returned status %d: %s", resp.StatusCode, string(body))
return nil, fmt.Errorf("bing API returned status %d: %s", resp.StatusCode, string(body))
}
var respData bingSearchResponse
if err := json.Unmarshal(body, &respData); err != nil {
return nil, fmt.Errorf("failed to unmarshal response: %w", err)
}
results := make([]*types.WebSearchResult, 0, len(respData.WebPages.Value))
for _, item := range respData.WebPages.Value {
results = append(results, &types.WebSearchResult{
Title: item.Name,
URL: item.URL,
Snippet: item.Snippet,
Source: "bing",
PublishedAt: &item.DateLastCrawled,
})
}
return results, nil
}
// bingSearchResponse defines the response structure for Bing search API.
type bingSearchResponse struct {
Type string `json:"_type"`
QueryContext struct {View on GitHub (pinned to 988cbb0330)
Solutions
- Log or inspect the raw body (the provider already has it in doSearch) to see what was actually returned.
- Confirm no corporate proxy or WAF is intercepting the request (headers, TLS MITM).
- Verify the Bing API version and that the endpoint still matches the struct definition (bingSearchResponse).
- Ensure the HTTP client is not double-decompressing or skipping gzip responses.
Example fix
// before
var respData bingSearchResponse
if err := json.Unmarshal(body, &respData); err != nil { ... }
// after
if !json.Valid(body) {
return nil, fmt.Errorf("non-JSON response body: %.200s", body)
}
var respData bingSearchResponse
if err := json.Unmarshal(body, &respData); err != nil { ... } Defensive patterns
Strategy: try-catch
Type guard
func isUnmarshalErr(err error) bool {
return err != nil && strings.Contains(err.Error(), "failed to unmarshal response")
} Try / catch
results, err := provider.Search(ctx, query, 10, false)
if err != nil && strings.Contains(err.Error(), "failed to unmarshal response") {
// log raw body via debug logging, fall back to another provider
return fallbackProvider.Search(ctx, query, 10, false)
} Prevention
- Enable request/response logging in staging to catch schema drift early.
- Keep bingSearchResponse struct in sync with the API version in use.
- Check json.Valid() on bodies when debugging unexpected unmarshal errors.
- Watch for proxy/WAF products injecting non-JSON content.
When it happens
Trigger: Bing returns HTML/XML error pages, a proxy/CAPTCHA response, or JSON missing the expected webPages.value structure; body was truncated by a network fault.
Common situations: Hitting a captive proxy that injects HTML; Bing changing/retiring its response schema; response gzip/compression not handled; a 200 response from a gateway instead of the real API.
Understand the failure class
Background: "failed to unmarshal" / json.Unmarshal errors: why parsing a response into a Go struct fails and how to fix it — this error's family across 23 libraries.
Related errors
- failed to parse HTML: %w
- failed to unmarshal response: %w
- failed to set FAQ metadata: %w
- decode suggestion JSON: %w
- marshal credentials: %w
AI-assisted analysis of Tencent/WeKnora@988cbb0330 (2026-09-02).
Data as JSON: /api/errors/93deaa04696df68f.
Report an issue: GitHub.