{"record":{"id":"f0b17050700aa514","repo":"Tencent/WeKnora","slug":"failed-to-decode-searxng-response-ensure-json-for","errorCode":null,"errorMessage":"failed to decode SearXNG response (ensure JSON format is enabled in settings.yml): %w","messagePattern":"failed to decode SearXNG response \\(ensure JSON format is enabled in settings\\.yml\\): %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/infrastructure/web_search/searxng.go","lineNumber":138,"sourceCode":"\t}\n\treq.Header.Set(\"Accept\", \"application/json\")\n\treq.Header.Set(\"User-Agent\", \"WeKnora/1.0\")\n\n\tresp, err := p.client.Do(req)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to execute request: %w\", err)\n\t}\n\tdefer resp.Body.Close()\n\n\tif resp.StatusCode != http.StatusOK {\n\t\tbody, _ := io.ReadAll(io.LimitReader(resp.Body, 1024))\n\t\treturn nil, fmt.Errorf(\"searxng returned status %d: %s\", resp.StatusCode, string(body))\n\t}\n\n\tvar data searxngResponse\n\tif err := json.NewDecoder(resp.Body).Decode(&data); err != nil {\n\t\tp.lastUnresponsive = nil\n\t\treturn nil, fmt.Errorf(\"failed to decode SearXNG response (ensure JSON format is enabled in settings.yml): %w\", err)\n\t}\n\tp.lastUnresponsive = data.UnresponsiveEngines\n\n\tresults := make([]*types.WebSearchResult, 0, maxResults)\n\tfor _, r := range data.Results {\n\t\tif len(results) >= maxResults {\n\t\t\tbreak\n\t\t}\n\t\tif r.URL == \"\" || r.Title == \"\" {\n\t\t\tcontinue\n\t\t}\n\t\titem := &types.WebSearchResult{\n\t\t\tTitle:   r.Title,\n\t\t\tURL:     r.URL,\n\t\t\tSnippet: r.Content,\n\t\t\tSource:  \"searxng\",\n\t\t}\n\t\tif includeDate && r.PublishedDate != \"\" {","sourceCodeStart":120,"sourceCodeEnd":156,"githubUrl":"https://github.com/Tencent/WeKnora/blob/988cbb03305e055d8ebb7d46d9ac6cc0803cd074/internal/infrastructure/web_search/searxng.go#L120-L156","documentation":"The HTTP response was status 200 but its body could not be decoded into the expected searxngResponse JSON shape. SearXNG by default returns HTML; JSON output must be explicitly enabled via the 'json' format in settings.yml, so a 200 HTML page (the search UI) fails json.Decode. The message explicitly hints at this configuration.","triggerScenarios":"Search() receiving a 200 response whose body is HTML (JSON format disabled), a proxy/interstitial page, or truncated/invalid JSON.","commonSituations":"Default SearXNG settings.yml without 'json' in search.formats; a reverse proxy or WAF returning an HTML challenge page with 200; misconfigured base URL hitting a different app that returns 200 HTML.","solutions":["Edit SearXNG settings.yml to add 'json' under search: formats: and restart the container","curl '<baseURL>/search?q=test&format=json' to confirm raw JSON comes back before integrating","Verify the baseURL points at the SearXNG root, not an HTML page or different service behind the same proxy","Inspect the actual body (log first 1KB on decode failure) to identify HTML/interstitial content"],"exampleFix":"# before (searxng/settings.yml)\nsearch:\n  formats:\n    - html\n# after\nsearch:\n  formats:\n    - html\n    - json","handlingStrategy":"validation","validationCode":"// verify the endpoint returns JSON, not HTML\nr, _ := http.Get(baseURL + \"/search?q=test&format=json\")\nb, _ := io.ReadAll(io.LimitReader(r.Body, 512))\nr.Body.Close()\nif !json.Valid(b) && !strings.HasPrefix(strings.TrimSpace(string(b)), \"{\") {\n    return fmt.Errorf(\"searxng did not return JSON; enable 'json' format in settings.yml\")\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Keep 'json' listed in search.formats and re-verify after SearXNG upgrades","Ensure reverse proxies don't inject HTML interstitials into API paths","Point baseURL at the SearXNG root, not an arbitrary page"],"tags":["json","decode-error","searxng","config","content-type"],"backgroundTag":"json-decode-failed","analyzedSha":"988cbb03305e055d8ebb7d46d9ac6cc0803cd074","analyzedAt":"2026-09-02T14:41:08.344Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}