crowdsecurity/crowdsec · error

unable to query PAPI : %s (%d)

Error message

unable to query PAPI : %s (%d)

What it means

GetPermissions queries the local PAPI (Pull API) service to check permissions. When PAPI returns a non-success HTTP status, the error response body is decoded and surfaced as 'unable to query PAPI : <message> (<status code>)'. It means the PAPI service itself responded but rejected or failed the request.

Source

Thrown at pkg/apiserver/papi.go:187

		return PapiPermCheckSuccess{}, fmt.Errorf("failed to create request: %w", err)
	}

	resp, err := httpClient.Do(req)
	if err != nil {
		return PapiPermCheckSuccess{}, fmt.Errorf("failed to get response: %w", err)
	}

	defer resp.Body.Close()

	if resp.StatusCode != http.StatusOK {
		errResp := PapiPermCheckError{}

		err = json.NewDecoder(resp.Body).Decode(&errResp)
		if err != nil {
			return PapiPermCheckSuccess{}, fmt.Errorf("failed to decode response: %w", err)
		}

		return PapiPermCheckSuccess{}, fmt.Errorf("unable to query PAPI : %s (%d)", errResp.Error, resp.StatusCode)
	}

	respBody := PapiPermCheckSuccess{}

	err = json.NewDecoder(resp.Body).Decode(&respBody)
	if err != nil {
		return PapiPermCheckSuccess{}, fmt.Errorf("failed to decode response: %w", err)
	}

	return respBody, nil
}

func reverse(s []longpollclient.Event) []longpollclient.Event {
	a := make([]longpollclient.Event, len(s))
	copy(a, s)

	for i := len(a)/2 - 1; i >= 0; i-- {
		opp := len(a) - 1 - i

View on GitHub (pinned to 909b515798)

Solutions

  1. Check the PAPI URL and credentials in the LAPI configuration (api.server.pull_api configuration section)
  2. Verify the PAPI service is enabled in the crowdsec API server config
  3. Inspect the embedded status code and PAPI error message in the log to identify the server-side cause
  4. Check network/proxy between crowdsec and the PAPI endpoint
Defensive patterns

Strategy: try-catch

Validate before calling

resp, err := client.Get(papiURL); if err != nil || resp.StatusCode >= 300 { /* handle before decode */ }

Try / catch

if _, err := GetPermissions(ctx); err != nil { if strings.Contains(err.Error(), "unable to query PAPI") { log.Printf("PAPI returned error: %v", err); /* fallback or retry */ } }

Prevention

When it happens

Trigger: The HTTP response from the PAPI server has a non-2xx status code; the body is successfully decoded into the error struct and its Error field plus status code are wrapped into this message.

Common situations: PAPI service misconfigured (wrong URL/port in lapi configuration), expired or invalid machine credentials, PAPI endpoint disabled in the API server config, or the service is unhealthy behind a proxy returning 5xx.

Understand the failure class

Background: "API error: {status}" and "HTTP 401/403/404/429/5xx" errors: non-2xx HTTP responses explained — this error's family across 27 libraries.

Related errors


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