crowdsecurity/crowdsec · error

longpoll API error message: %s

Error message

longpoll API error message: %s

What it means

The long-poll server answered successfully, but the decoded response carried a non-empty ErrorMessage field that is not the special timeout sentinel ("no events before timeout"). The client turns that server-side message into a Go error so the caller (pollEvents) treats it as a poll failure.

Source

Thrown at pkg/longpollclient/client.go:139

		default:
			var pollResp pollResponse
			err = decoder.Decode(&pollResp)
			if err != nil {
				if errors.Is(err, io.EOF) {
					logger.Debugf("server closed connection")
					return nil
				}
				return fmt.Errorf("error decoding poll response: %v", err)
			}

			logger.Tracef("got response: %+v", pollResp)

			if pollResp.ErrorMessage != "" {
				if pollResp.ErrorMessage == timeoutMessage {
					logger.Debugf("got timeout message")
					return nil
				}
				return fmt.Errorf("longpoll API error message: %s", pollResp.ErrorMessage)
			}

			if len(pollResp.Events) > 0 {
				logger.Debugf("got %d events", len(pollResp.Events))
				for _, event := range pollResp.Events {
					event.RequestId = requestId
					c.c <- event
					if event.Timestamp > c.since {
						c.since = event.Timestamp
					}
				}
			}
			if pollResp.Timestamp > 0 {
				c.since = pollResp.Timestamp
			}
			logger.Debugf("Since is now %d", c.since)
		}
	}

View on GitHub (pinned to 909b515798)

Solutions

  1. Read the %s payload — it is the server's own error text; fix the request or server condition it describes.
  2. Verify the client's query parameters (channel/filters/since) are valid for the connected LAPI version.
  3. Check LAPI server logs for the matching error at the same timestamp.
  4. Ensure auth is valid — some server errors stem from expired/insufficient bouncer credentials.
Defensive patterns

Strategy: try-catch

Validate before calling

// before polling, sanity-check request params
if lastDate != "" {
    if _, err := time.Parse(time.RFC3339, lastDate); err != nil {
        return fmt.Errorf("invalid last-date filter: %w", err)
    }
}

Try / catch

// surface the server's own message to operators
if err := client.Poll(); err != nil {
    var apiErr string
    if strings.Contains(err.Error(), "longpoll API error message:") {
        fmt.Sscanf(err.Error(), "longpoll API error message: %s", &apiErr)
        logger.Errorf("LAPI rejected poll: %s", apiErr)
    }
    return err
}

Prevention

When it happens

Trigger: poll() decodes a pollResp whose ErrorMessage is non-empty and != timeoutMessage; e.g. the LAPI rejected the request parameters or reported an internal error while producing the response.

Common situations: Requesting events with a filter/last-date the LAPI cannot honor; LAPI internal error during decision lookup; using a bouncer with parameters unsupported by the server version.

Related errors


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