{"record":{"id":"0d2893310d625bf2","repo":"crowdsecurity/crowdsec","slug":"unable-to-query-papi-s-d","errorCode":null,"errorMessage":"unable to query PAPI : %s (%d)","messagePattern":"unable to query PAPI : (.+?) \\((.+?)\\)","errorType":"http","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/apiserver/papi.go","lineNumber":187,"sourceCode":"\t\treturn PapiPermCheckSuccess{}, fmt.Errorf(\"failed to create request: %w\", err)\n\t}\n\n\tresp, err := httpClient.Do(req)\n\tif err != nil {\n\t\treturn PapiPermCheckSuccess{}, fmt.Errorf(\"failed to get response: %w\", err)\n\t}\n\n\tdefer resp.Body.Close()\n\n\tif resp.StatusCode != http.StatusOK {\n\t\terrResp := PapiPermCheckError{}\n\n\t\terr = json.NewDecoder(resp.Body).Decode(&errResp)\n\t\tif err != nil {\n\t\t\treturn PapiPermCheckSuccess{}, fmt.Errorf(\"failed to decode response: %w\", err)\n\t\t}\n\n\t\treturn PapiPermCheckSuccess{}, fmt.Errorf(\"unable to query PAPI : %s (%d)\", errResp.Error, resp.StatusCode)\n\t}\n\n\trespBody := PapiPermCheckSuccess{}\n\n\terr = json.NewDecoder(resp.Body).Decode(&respBody)\n\tif err != nil {\n\t\treturn PapiPermCheckSuccess{}, fmt.Errorf(\"failed to decode response: %w\", err)\n\t}\n\n\treturn respBody, nil\n}\n\nfunc reverse(s []longpollclient.Event) []longpollclient.Event {\n\ta := make([]longpollclient.Event, len(s))\n\tcopy(a, s)\n\n\tfor i := len(a)/2 - 1; i >= 0; i-- {\n\t\topp := len(a) - 1 - i","sourceCodeStart":169,"sourceCodeEnd":205,"githubUrl":"https://github.com/crowdsecurity/crowdsec/blob/909b5157986a2b2c2163300fdaef5ed01289f7d2/pkg/apiserver/papi.go#L169-L205","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Check the PAPI URL and credentials in the LAPI configuration (api.server.pull_api configuration section)","Verify the PAPI service is enabled in the crowdsec API server config","Inspect the embedded status code and PAPI error message in the log to identify the server-side cause","Check network/proxy between crowdsec and the PAPI endpoint"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"resp, err := client.Get(papiURL); if err != nil || resp.StatusCode >= 300 { /* handle before decode */ }","typeGuard":null,"tryCatchPattern":"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 */ } }","preventionTips":["Keep PAPI credentials and URL in config validated at startup","Monitor PAPI endpoint health before scheduled pulls","Pin compatible crowdsec versions across components"],"tags":["http","papi","api"],"backgroundTag":"http-error-response","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"}