crowdsecurity/crowdsec · error
unable to create alert: no IDs returned for alert %s
Error message
unable to create alert: no IDs returned for alert %s
What it means
A defensive invariant check: after CreateAlert reports success, the code expects at least one alert ID back. If the returned ID slice is empty (marked 'happy nilaway'), it returns 'unable to create alert: no IDs returned for alert %s'. This indicates an internal inconsistency — CreateAlert succeeded but returned no identifier — rather than a user-facing input problem.
Source
Thrown at pkg/database/alerts.go:64
if alertItem.UUID == "" {
return "", errors.New("alert UUID is empty")
}
alerts, err := c.Ent.Alert.Query().Where(alert.UUID(alertItem.UUID)).WithDecisions().All(ctx)
if err != nil && !ent.IsNotFound(err) {
return "", fmt.Errorf("unable to query alerts for uuid %s: %w", alertItem.UUID, err)
}
// alert wasn't found, insert it (expected hotpath)
if ent.IsNotFound(err) || len(alerts) == 0 {
alertIDs, err := c.CreateAlert(ctx, machineID, []*models.Alert{alertItem})
if err != nil {
return "", fmt.Errorf("unable to create alert: %w", err)
}
// happy nilaway
if len(alertIDs) == 0 {
return "", fmt.Errorf("unable to create alert: no IDs returned for alert %s", alertItem.UUID)
}
return alertIDs[0], nil
}
// this should never happen
if len(alerts) > 1 {
return "", fmt.Errorf("multiple alerts found for uuid %s", alertItem.UUID)
}
log.Infof("Alert %s already exists, checking associated decisions", alertItem.UUID)
// alert is found, check for any missing decisions
newUuids := make([]string, len(alertItem.Decisions))
for i, decItem := range alertItem.Decisions {
newUuids[i] = decItem.UUID
}View on GitHub (pinned to 909b515798)
Solutions
- Retry the alert push; the UUID lookup makes it idempotent
- Check the crowdsec version for known CreateAlert bugs and upgrade
- Capture logs and report upstream (github.com/crowdsec/crowdsec/issues) with the crowdsec version and DB backend
- Verify with 'cscli alerts list' whether the alert was actually persisted despite the empty ID list
Defensive patterns
Strategy: fallback
Try / catch
id, err := client.CreateOrUpdateAlert(ctx, machineID, alert)
if err != nil && strings.Contains(err.Error(), "no IDs returned") {
// verify actual persistence instead of trusting the ID
alerts, qErr := client.QueryAlertWithUUID(ctx, alert.UUID)
if qErr == nil && len(alerts) == 1 { id = alerts[0].UUID }
} Prevention
- Keep crowdsec up to date; this is an internal invariant, not a user error
- Verify persistence via alert queries if the returned ID is empty
- Report reproducible occurrences upstream with version and DB backend details
When it happens
Trigger: CreateAlert returns a non-nil, empty []string ID slice for a freshly inserted alert. Should be unreachable in normal operation; would occur only from an internal regression in CreateAlert's bulk-insert ID collection logic.
Common situations: Essentially only seen after a crowdsec bug or a modified/custom build; if encountered, it points to a defect in the alert insertion code path rather than to user configuration.
Understand the failure class
Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.
Related errors
- cannot create %s reader
- path must start with /
- mtls is selected, but ca_cert is not provided
- invalid auth_type: must be one of basic_auth, headers, mtls
- server_cert is required
AI-assisted analysis of crowdsecurity/crowdsec@909b515798 (2026-09-06).
Data as JSON: /api/errors/6190c51a26b04776.
Report an issue: GitHub.