crowdsecurity/crowdsec · error
api register (%s) http %s: %w
Error message
api register (%s) http %s: %w
What it means
RegisterClient posts a watcher registration to the LAPI; when the server answers with an HTTP error status (the response object is available), the error includes the base URL and HTTP status plus the underlying body error. It distinguishes server-rejected registrations (which have a status) from pure transport failures (handled by the sibling error at line 296).
Source
Thrown at pkg/apiclient/client.go:293
client.Transport = transport
}
userAgent := config.UserAgent
if userAgent == "" {
userAgent = useragent.Default()
}
c := &ApiClient{client: client, BaseURL: baseURL, UserAgent: userAgent, URLPrefix: config.VersionPrefix}
c.common.client = c
c.Decisions = (*DecisionsService)(&c.common)
c.Alerts = (*AlertsService)(&c.common)
c.Auth = (*AuthService)(&c.common)
resp, err := c.Auth.RegisterWatcher(ctx, models.WatcherRegistrationRequest{MachineID: &config.MachineID, Password: &config.Password, RegistrationToken: config.RegistrationToken})
if err != nil {
/*if we have http status, return it*/
if resp != nil && resp.Response != nil {
return nil, fmt.Errorf("api register (%s) http %s: %w", c.BaseURL, resp.Response.Status, err)
}
return nil, fmt.Errorf("api register (%s): %w", c.BaseURL, err)
}
return c, nil
}
func createTransport(url *url.URL) (*http.Transport, *url.URL) {
urlString := url.String()
// TCP transport
if !strings.HasPrefix(urlString, "/") {
return nil, url
}
// Unix transport
url.Path = "/"View on GitHub (pinned to 909b515798)
Solutions
- If the machine already exists, either use existing credentials ('cscli machines list'/'cscli lapi register' reuse) or delete and re-register the machine
- Verify the registration token (yaml flag or env) matches one issued by 'cscli machines add --token' on the LAPI host
- Read the HTTP status in the message: 400/409 = duplicate or malformed request, 403 = token/auth rejection, 5xx = LAPI-side failure
- Check LAPI server logs for the corresponding registration rejection reason
Example fix
// before
resp, err := c.Auth.RegisterWatcher(ctx, models.WatcherRegistrationRequest{MachineID: &config.MachineID, ...})
// after (caller guards against duplicate registration)
if machineAlreadyRegistered(config.MachineID) {
return nil, fmt.Errorf("machine %q already registered; reuse credentials or delete it first", config.MachineID)
}
resp, err := c.Auth.RegisterWatcher(ctx, models.WatcherRegistrationRequest{MachineID: &config.MachineID, ...}) Defensive patterns
Strategy: validation
Validate before calling
// check for an existing registration before re-registering
machines, _, err := existingClient.Machines.List(ctx)
if err == nil {
for _, m := range machines {
if m.MachineId != nil && *m.MachineId == config.MachineID {
return errors.New("machine already registered; reuse existing credentials")
}
}
} Type guard
func hasHTTPStatus(err error) (string, bool) {
var apiErr *apiclient.APIError
if errors.As(err, &apiErr) {
return apiErr.Status, true
}
return "", false
} Try / catch
_, err := apiclient.RegisterClient(ctx, config, nil)
if err != nil {
var apiErr *apiclient.APIError
if errors.As(err, &apiErr) && (apiErr.StatusCode == 409 || apiErr.StatusCode == 400) {
// machine already registered: fetch/reuse credentials instead of failing
}
return err
} Prevention
- Don't re-run 'cscli lapi register' blindly; check existing machines first
- Generate registration tokens with 'cscli machines add --token' and use them before expiry
- Read the HTTP status embedded in the message before debugging further
- Keep registration automated in one idempotent provisioning step
When it happens
Trigger: c.Auth.RegisterWatcher returns err while resp.Response is non-nil: e.g. 409/400 because the machine is already registered, 403 for a bad/expired registration token, or 500 from LAPI during POST to /watchers.
Common situations: Re-running 'cscli lapi register' against a LAPI where the machine ID already exists; using a registration token that is invalid or revoked; LAPI refusing auto-registration because it was disabled; reverse proxy returning an error page.
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
- api register (%s): %w
- unexpected status code: %d
- appsec datasource requires a hub. this is a bug, please repo
- appsec datasource requires a lapi client configuration. this
- missing lapi client credentials
AI-assisted analysis of crowdsecurity/crowdsec@909b515798 (2026-09-06).
Data as JSON: /api/errors/d320dfcf0017cdfc.
Report an issue: GitHub.