{"record":{"id":"c1b91008652366a2","repo":"crowdsecurity/crowdsec","slug":"websocket-error-w","errorCode":null,"errorMessage":"websocket error: %w","messagePattern":"websocket error: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/acquisition/modules/loki/internal/lokiclient/loki_client.go","lineNumber":294,"sourceCode":"\n\tconn, resp, err := dialer.Dial(u, requestHeader)\n\tif resp != nil && resp.Body != nil {\n\t\t_ = resp.Body.Close()\n\t}\n\tif err != nil {\n\t\tlc.Logger.Errorf(\"Error connecting to websocket, err: %s\", err)\n\t\treturn responseChan, errors.New(\"error connecting to websocket\")\n\t}\n\n\tlc.t.Go(func() error {\n\t\tdefer conn.Close()\n\t\tfor {\n\t\t\tjsonResponse := &LokiResponse{}\n\n\t\t\terr = conn.ReadJSON(jsonResponse)\n\t\t\tif err != nil {\n\t\t\t\tlc.Logger.Errorf(\"Error reading from websocket: %s\", err)\n\t\t\t\treturn fmt.Errorf(\"websocket error: %w\", err)\n\t\t\t}\n\n\t\t\tresponseChan <- jsonResponse\n\t\t}\n\t})\n\n\treturn responseChan, nil\n}\n\nfunc (lc *LokiClient) QueryRange(ctx context.Context, infinite bool) chan *LokiQueryRangeResponse {\n\turl := lc.getURLFor(\"loki/api/v1/query_range\", map[string]string{\n\t\t\"query\":     lc.config.Query,\n\t\t\"start\":     strconv.FormatInt(time.Now().Add(-lc.config.Since).UnixNano(), 10),\n\t\t\"end\":       strconv.FormatInt(time.Now().UnixNano(), 10),\n\t\t\"limit\":     strconv.Itoa(lc.config.Limit),\n\t\t\"direction\": \"forward\",\n\t})\n","sourceCodeStart":276,"sourceCodeEnd":312,"githubUrl":"https://github.com/crowdsecurity/crowdsec/blob/909b5157986a2b2c2163300fdaef5ed01289f7d2/pkg/acquisition/modules/loki/internal/lokiclient/loki_client.go#L276-L312","documentation":"In the Loki tail (websocket) worker, conn.ReadJSON failed when reading a streamed message — typically because the websocket connection dropped (Loki restart, network cut, idle timeout). The goroutine returns 'websocket error' wrapping the read failure and stops feeding responseChan.","triggerScenarios":"Loki closes the websocket (shutdown, keepalive expiry, limit of connections), TCP reset, or a non-JSON frame arrives.","commonSituations":"Loki pods restarted behind a load balancer; proxies with short idle timeouts killing long-lived websockets; network interruptions.","solutions":["Restart the datasource — the tail worker should be relaunched to re-establish the websocket","Check proxy/LB idle timeouts and enable websocket keepalive/ping support","Ensure Loki is stable and check its logs for shutdown causes"],"exampleFix":null,"handlingStrategy":"retry","validationCode":"// preflight: confirm /loki/api/v1/tail is reachable and websockets are allowed through proxies\ncurl -i -N -H 'Connection: Upgrade' -H 'Upgrade: websocket' 'http://loki:3100/loki/api/v1/tail?query=%7Bjob%3D%22app%22%7D'","typeGuard":null,"tryCatchPattern":"for {\n    err := runTail(ctx, responseChan)\n    if ctx.Err() != nil { return }\n    log.Warnf(\"tail dropped: %v; reconnecting in 5s\", err)\n    select {\n    case <-time.After(5 * time.Second):\n    case <-ctx.Done(): return\n    }\n}","preventionTips":["Raise proxy/LB idle timeouts for websocket routes","Ensure Loki uses connection keepalive/pings on tail streams","Wrap the tail worker with automatic reconnect logic"],"tags":["loki","websocket","network"],"backgroundTag":"connection-refused","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"}