Tencent/WeKnora · error
failed to unmarshal response: %w
Error message
failed to unmarshal response: %w
What it means
The Ollama provider received a 200 response but the body could not be parsed into ollamaSearchResponse. fmt.Errorf with %w wraps the underlying json.Unmarshal error, so the exact JSON syntax/type mismatch is preserved in the chain.
Source
Thrown at internal/infrastructure/web_search/ollama.go:130
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][Ollama] API returned status %d: %s", resp.StatusCode, string(body))
return nil, fmt.Errorf("ollama API returned status %d: %s", resp.StatusCode, string(body))
}
var respData ollamaSearchResponse
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.Results))
for _, item := range respData.Results {
results = append(results, &types.WebSearchResult{
Title: item.Title,
URL: item.URL,
Snippet: item.Snippet,
Content: item.Content,
Source: "ollama",
})
}
return results, nil
}
// ollamaSearchResponse defines the response structure for Ollama web search API.
type ollamaSearchResponse struct {
Results []ollamaSearchResult `json:"results"`View on GitHub (pinned to 988cbb0330)
Solutions
- Log or print the raw body to see what was actually returned
- Verify the endpoint really is the Ollama search API (no proxy/HTML response)
- Check Ollama version compatibility with the expected response schema
- Update the client struct to match the actual API schema if the API changed
Example fix
// before
// struct expects {"results":[{"title":...}]}
// after: inspect body first
if !json.Valid(body) { return nil, fmt.Errorf("non-JSON response: %.200s", body) } Defensive patterns
Strategy: try-catch
Validate before calling
// sanity-check endpoint returns JSON before use
resp, err := http.Get(baseURL + healthPath)
if err == nil {
ct := resp.Header.Get("Content-Type")
if !strings.Contains(ct, "application/json") {
return fmt.Errorf("endpoint does not return JSON: %s", ct)
}
} Type guard
func isUnmarshalError(err error) bool {
return err != nil && strings.Contains(err.Error(), "failed to unmarshal response")
} Try / catch
results, err := provider.Search(ctx, q)
if err != nil {
if isUnmarshalError(err) {
log.Printf("Ollama returned non-JSON/changed schema: %v", err)
return fallbackSearch(ctx, q)
}
return err
} Prevention
- Ensure no proxy returns HTML for API routes
- Test the response schema after any Ollama version upgrade
- Check Content-Type before unmarshalling when possible
- Keep the response struct updated with the deployed Ollama API version
When it happens
Trigger: Search -> doSearch receives HTTP 200 but the body is not the expected JSON shape: HTML from a misconfigured proxy, truncated response, or Ollama returning a schema that changed.
Common situations: A reverse proxy intercepts requests and returns HTML, an old/new Ollama version changes response fields, network middleware corrupts the payload, or the wrong port serves a different service.
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
- unmarshal block: %w
- args must be a string or an array of strings: %w
- logical operator %s requires an array of conditions
- failed to unmarshal condition at index %d: %w
- unmarshal page: %w
AI-assisted analysis of Tencent/WeKnora@988cbb0330 (2026-09-02).
Data as JSON: /api/errors/9451a3883d7106ef.
Report an issue: GitHub.