crowdsecurity/crowdsec · error
failed to create PAPI client: %w
Error message
failed to create PAPI client: %w
What it means
NewPAPI builds the Polling API (PAPI) client by constructing a long-poll HTTP client pointed at the CAPI decisions/stream/poll endpoint. This error wraps any failure from longpollclient.NewLongPollClient (typically URL parsing or HTTP client configuration problems) and aborts PAPI subsystem initialization, so the server cannot receive push-style decision/alert orders from the central API.
Source
Thrown at pkg/apiserver/papi.go:102
Plan string `json:"plan"`
Categories []string `json:"categories"`
}
func NewPAPI(apic *apic, dbClient *database.Client, consoleConfig *csconfig.ConsoleConfig, logger logging.ExtLogger) (*Papi, error) {
if logger == nil {
logger = log.StandardLogger()
}
papiURL := *apic.apiClient.PapiURL
papiURL.Path = fmt.Sprintf("%s%s", PAPIVersion, PAPIPollURL)
longPollClient, err := longpollclient.NewLongPollClient(longpollclient.LongPollClientConfig{
Url: papiURL,
Logger: logger,
HttpClient: apic.apiClient.GetClient(),
})
if err != nil {
return &Papi{}, fmt.Errorf("failed to create PAPI client: %w", err)
}
channels := &OperationChannels{
AddAlertChannel: apic.AlertsAddChan,
DeleteDecisionChannel: make(chan []*models.Decision),
}
papi := &Papi{
URL: apic.apiClient.PapiURL.String(),
Client: longPollClient,
DBClient: dbClient,
Channels: channels,
SyncInterval: SyncInterval,
mu: sync.Mutex{},
pullTomb: tomb.Tomb{},
syncTomb: tomb.Tomb{},
apiClient: apic.apiClient,
apic: apic,View on GitHub (pinned to 909b515798)
Solutions
- Read the wrapped error after 'failed to create PAPI client:' — it names the exact cause (usually URL parse failure).
- Check config.yaml: api.client.papi_url must be a valid absolute URL (default https://api.crowdsec.net).
- Validate the whole api.client section (url, login, password, ca_cert_path, insecure_skip_verify) with `crowdsec -c config.yaml -t` (config test).
- Restore the default papi_url if it was hand-edited, then restart crowdsec.
Example fix
// before (config.yaml)
api:
client:
papi_url: api.crowdsec.net/v1 # missing scheme
// after
api:
client:
papi_url: https://api.crowdsec.net/ Defensive patterns
Strategy: try-catch
Validate before calling
u, err := url.Parse(cfg.API.Client.PapiURL)
if err != nil || u.Scheme == "" || u.Host == "" {
return fmt.Errorf("invalid papi_url %q", cfg.API.Client.PapiURL)
} Try / catch
papi, err := NewPAPI(apic, dbClient, consoleConfig, logger)
if err != nil {
var urlErr *url.Error
if errors.As(err, &urlErr) {
logger.Errorf("PAPI URL misconfigured: %v", urlErr)
}
return err
} Prevention
- Run `crowdsec -t` (config test) after any edit to the api.client section.
- Never hand-edit papi_url unless instructed; keep the upstream default.
- Use `crowdsec config check`-style tooling or cscli to validate YAML before restart.
- Validate URL values loaded from env/templating for stray whitespace and missing scheme.
When it happens
Trigger: Called from NewServer during apiserver startup (and by sync/QueryPAPIInfo) when api.client.papi_url is misconfigured or the underlying http client from apic.apiClient.GetClient() cannot be prepared — e.g. the papi URL fails to parse in NewLongPollClient.
Common situations: Malformed or missing api.client.papi_url in config.yaml; corrupt api section config after manual edits; network proxy/TLS client misconfiguration (insecure_skip_verify/ca_cert path issues) that makes client construction fail at boot.
Understand the failure class
Background: "Invalid URL" errors: why new URL(), URI.parse, and reqwest::Url reject your string — missing scheme, whitespace, and bad path format — this error's family across 39 libraries.
Related errors
- no configuration paths provided
- compilation of '%s' context value failed: %w
- while parsing '%s': %w
- failed to compile profiles: %w
- failed to create request: %w
AI-assisted analysis of crowdsecurity/crowdsec@909b515798 (2026-09-06).
Data as JSON: /api/errors/4f3c5ff72fd7a4d8.
Report an issue: GitHub.