crowdsecurity/crowdsec · error

websocket error: %w

Error message

websocket error: %w

What it means

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.

Source

Thrown at pkg/acquisition/modules/loki/internal/lokiclient/loki_client.go:294

	conn, resp, err := dialer.Dial(u, requestHeader)
	if resp != nil && resp.Body != nil {
		_ = resp.Body.Close()
	}
	if err != nil {
		lc.Logger.Errorf("Error connecting to websocket, err: %s", err)
		return responseChan, errors.New("error connecting to websocket")
	}

	lc.t.Go(func() error {
		defer conn.Close()
		for {
			jsonResponse := &LokiResponse{}

			err = conn.ReadJSON(jsonResponse)
			if err != nil {
				lc.Logger.Errorf("Error reading from websocket: %s", err)
				return fmt.Errorf("websocket error: %w", err)
			}

			responseChan <- jsonResponse
		}
	})

	return responseChan, nil
}

func (lc *LokiClient) QueryRange(ctx context.Context, infinite bool) chan *LokiQueryRangeResponse {
	url := lc.getURLFor("loki/api/v1/query_range", map[string]string{
		"query":     lc.config.Query,
		"start":     strconv.FormatInt(time.Now().Add(-lc.config.Since).UnixNano(), 10),
		"end":       strconv.FormatInt(time.Now().UnixNano(), 10),
		"limit":     strconv.Itoa(lc.config.Limit),
		"direction": "forward",
	})

View on GitHub (pinned to 909b515798)

Solutions

  1. Restart the datasource — the tail worker should be relaunched to re-establish the websocket
  2. Check proxy/LB idle timeouts and enable websocket keepalive/ping support
  3. Ensure Loki is stable and check its logs for shutdown causes
Defensive patterns

Strategy: retry

Validate before calling

// preflight: confirm /loki/api/v1/tail is reachable and websockets are allowed through proxies
curl -i -N -H 'Connection: Upgrade' -H 'Upgrade: websocket' 'http://loki:3100/loki/api/v1/tail?query=%7Bjob%3D%22app%22%7D'

Try / catch

for {
    err := runTail(ctx, responseChan)
    if ctx.Err() != nil { return }
    log.Warnf("tail dropped: %v; reconnecting in 5s", err)
    select {
    case <-time.After(5 * time.Second):
    case <-ctx.Done(): return
    }
}

Prevention

When it happens

Trigger: Loki closes the websocket (shutdown, keepalive expiry, limit of connections), TCP reset, or a non-JSON frame arrives.

Common situations: Loki pods restarted behind a load balancer; proxies with short idle timeouts killing long-lived websockets; network interruptions.

Understand the failure class

Background: ECONNREFUSED and "connection refused" / "could not connect to server" errors: what they mean and how to fix them — this error's family across 44 libraries.

Related errors


AI-assisted analysis of crowdsecurity/crowdsec@909b515798 (2026-09-06). Data as JSON: /api/errors/c1b91008652366a2. Report an issue: GitHub.