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

  1. If the machine already exists, either use existing credentials ('cscli machines list'/'cscli lapi register' reuse) or delete and re-register the machine
  2. Verify the registration token (yaml flag or env) matches one issued by 'cscli machines add --token' on the LAPI host
  3. Read the HTTP status in the message: 400/409 = duplicate or malformed request, 403 = token/auth rejection, 5xx = LAPI-side failure
  4. 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

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


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