{"record":{"id":"07f803c2079d9d68","repo":"crowdsecurity/crowdsec","slug":"loki-channel-closed","errorCode":null,"errorMessage":"loki channel closed","messagePattern":"loki channel closed","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/acquisition/modules/loki/run.go","lineNumber":103,"sourceCode":"\t\tif err := l.Client.Ready(readyCtx); err != nil {\n\t\t\treturn fmt.Errorf(\"loki is not ready: %w\", err)\n\t\t}\n\t}\n\n\tll := l.logger.WithField(\"websocket_url\", l.lokiWebsocket)\n\n\tt.Go(func() error {\n\t\tctx, cancel := context.WithCancel(ctx)\n\t\tdefer cancel()\n\n\t\trespChan := l.Client.QueryRange(ctx, true)\n\n\t\tfor {\n\t\t\tselect {\n\t\t\tcase resp, ok := <-respChan:\n\t\t\t\tif !ok {\n\t\t\t\t\tll.Warnf(\"loki channel closed\")\n\t\t\t\t\treturn errors.New(\"loki channel closed\")\n\t\t\t\t}\n\n\t\t\t\tfor _, stream := range resp.Data.Result {\n\t\t\t\t\tfor _, entry := range stream.Entries {\n\t\t\t\t\t\tl.readOneEntry(entry, l.Config.Labels, out)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\tcase <-t.Dying():\n\t\t\t\treturn nil\n\t\t\t}\n\t\t}\n\t})\n\n\treturn nil\n}\n","sourceCodeStart":85,"sourceCodeEnd":119,"githubUrl":"https://github.com/crowdsecurity/crowdsec/blob/909b5157986a2b2c2163300fdaef5ed01289f7d2/pkg/acquisition/modules/loki/run.go#L85-L119","documentation":"During the tail loop, the channel delivering Loki websocket responses was closed without an error, which is treated as an abnormal termination. The source logs a warning and returns this error so crowdsec can restart or report the datasource failure.","triggerScenarios":"The loki client goroutine closed respChan (e.g. after a fatal websocket read error or shutdown) while the run loop in Run() was still reading from it.","commonSituations":"Loki server closed the tail connection (restart, timeout, proxy idle cutoff) or an internal client error caused the channel producer to exit.","solutions":["Check earlier logs for the websocket error that closed the channel and fix connectivity to Loki","Ensure Loki's tail stream isn't cut by proxies (raise idle timeouts)","Restart/reload crowdsec so the datasource reconnects","Upgrade if this recurs on every Loki restart (reconnect behavior)"],"exampleFix":null,"handlingStrategy":"retry","validationCode":"// ensure Loki is up and tail endpoint responds before streaming\nresp, err := http.Get(lokiURL + \"/loki/api/v1/tail?query=\" + url.QueryEscape(q))\nif err != nil {\n    return err\n}\nresp.Body.Close()","typeGuard":null,"tryCatchPattern":"respChan, err := tail()\nif err != nil { return err }\nfor resp := range respChan {\n    _ = resp\n}\n// on closed channel: reconnect with backoff","preventionTips":["Raise proxy idle/LB timeouts for long-lived websockets","Add automatic reconnect with backoff","Monitor Loki restarts","Keep crowdsec updated for reconnect fixes"],"tags":["loki","websocket","streaming","channel"],"backgroundTag":"broken-pipe","analyzedSha":"909b5157986a2b2c2163300fdaef5ed01289f7d2","analyzedAt":"2026-09-06T12:27:26.012Z","contentChangedAt":"2026-09-06T12:27:26.012Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}