{"record":{"id":"b65caeefd87f922d","repo":"crowdsecurity/crowdsec","slug":"error-decoding-loki-response-w","errorCode":null,"errorMessage":"error decoding Loki response: %w","messagePattern":"error decoding Loki response: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/acquisition/modules/loki/internal/lokiclient/loki_client.go","lineNumber":160,"sourceCode":"\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tif resp.StatusCode != http.StatusOK {\n\t\t\t\tlc.Logger.Warnf(\"bad HTTP response code for query range: %d\", resp.StatusCode)\n\t\t\t\tbody, _ := io.ReadAll(resp.Body)\n\t\t\t\tresp.Body.Close()\n\t\t\t\tif ok := lc.shouldRetry(); !ok {\n\t\t\t\t\treturn fmt.Errorf(\"bad HTTP response code: %d: %s: %w\", resp.StatusCode, string(body), err)\n\t\t\t\t}\n\t\t\t\tlc.increaseTicker(ticker)\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tvar lq LokiQueryRangeResponse\n\t\t\tif err := json.NewDecoder(resp.Body).Decode(&lq); err != nil {\n\t\t\t\tresp.Body.Close()\n\t\t\t\tif ok := lc.shouldRetry(); !ok {\n\t\t\t\t\treturn fmt.Errorf(\"error decoding Loki response: %w\", err)\n\t\t\t\t}\n\t\t\t\tlc.increaseTicker(ticker)\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tresp.Body.Close()\n\t\t\tlc.Logger.Tracef(\"Got response: %+v\", lq)\n\t\t\tc <- &lq\n\t\t\tlc.resetFailStart()\n\t\t\tif !infinite && (len(lq.Data.Result) == 0 || len(lq.Data.Result[0].Entries) < lc.config.Limit) {\n\t\t\t\tlc.Logger.Infof(\"Got less than %d results (%d), stopping\", lc.config.Limit, len(lq.Data.Result))\n\t\t\t\tclose(c)\n\t\t\t\treturn nil\n\t\t\t}\n\t\t\tif len(lq.Data.Result) > 0 {\n\t\t\t\tlc.Logger.Debugf(\"(timer:%v) %d results / %d entries result[0] (uri:%s)\", lc.currentTickerInterval, len(lq.Data.Result), len(lq.Data.Result[0].Entries), uri)\n\t\t\t} else {\n\t\t\t\tlc.Logger.Debugf(\"(timer:%v) no results (uri:%s)\", lc.currentTickerInterval, uri)\n\t\t\t}","sourceCodeStart":142,"sourceCodeEnd":178,"githubUrl":"https://github.com/crowdsecurity/crowdsec/blob/909b5157986a2b2c2163300fdaef5ed01289f7d2/pkg/acquisition/modules/loki/internal/lokiclient/loki_client.go#L142-L178","documentation":"queryRange received HTTP 200 but the body could not be decoded into LokiQueryRangeResponse (invalid or structurally unexpected JSON). After retries are exhausted, the decode error is wrapped and returned.","triggerScenarios":"Loki returns HTML (auth portal, error page) with 200; an intermediate proxy mangles the body; a Loki version returns a different JSON schema.","commonSituations":"Basic-auth login pages returned with 200; reverse proxies intercepting requests; version mismatch between expected and actual Loki API response fields.","solutions":["Inspect the raw response body via curl to see what Loki actually returns","Check for auth redirects/proxies in front of Loki","Align Loki version with the expected query_range response schema"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// probe raw body first:\n// body, _ := io.ReadAll(resp); var probe map[string]any\n// if json.Unmarshal(body, &probe) != nil || probe[\"data\"] == nil { /* not a Loki API response */ }","typeGuard":null,"tryCatchPattern":"if err := json.NewDecoder(resp.Body).Decode(&lq); err != nil {\n    log.Errorf(\"non-JSON or unexpected Loki response; check for auth portal/proxy: %v\", err)\n    return err\n}","preventionTips":["Ensure no auth redirect or proxy injects HTML into the response","Pin and test the Loki version compatibility","Check response Content-Type is application/json"],"tags":["loki","json","http"],"backgroundTag":"invalid-json-response","analyzedSha":"909b5157986a2b2c2163300fdaef5ed01289f7d2","analyzedAt":"2026-09-06T12:27:26.012Z","contentChangedAt":"2026-09-06T12:27:26.012Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}