crowdsecurity/crowdsec · error

unable to query alerts for uuid %s: %w

Error message

unable to query alerts for uuid %s: %w

What it means

CreateOrUpdateAlert queries the alerts table for an alert by UUID; if the ent query itself fails with an error other than not-found, the alert cannot be checked and this wrapped error is returned. It means the lookup SELECT against the alert repository failed, not that the alert is missing (missing alerts are handled by inserting a new one).

Source

Thrown at pkg/database/alerts.go:52

func rollbackOnError(tx *ent.Tx, err error, msg string) error {
	if rbErr := tx.Rollback(); rbErr != nil {
		log.Errorf("rollback error: %v", rbErr)
	}

	return fmt.Errorf("%s: %w", msg, err)
}

// CreateOrUpdateAlert is specific to PAPI : It checks if alert already exists, otherwise inserts it
// if alert already exists, it checks it associated decisions already exists
// if some associated decisions are missing (ie. previous insert ended up in error) it inserts them
func (c *Client) CreateOrUpdateAlert(ctx context.Context, machineID string, alertItem *models.Alert) (string, error) {
	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

View on GitHub (pinned to 909b515798)

Solutions

  1. Check DB connectivity and credentials in crowdsec's db_config
  2. Run 'cscli db migrate' / confirm the DB schema matches the installed crowdsec version
  3. For SQLite locks, look for other processes holding the DB and consider moving to PostgreSQL/MySQL
  4. Retry the operation once connectivity/locks are resolved; the operation is idempotent by alert UUID

Example fix

// before: treating any error as fatal without checking DB
// after: surface the cause and verify DB health first
if _, err := client.CreateOrUpdateAlert(ctx, machineID, alert); err != nil {
    if err := dbHealthCheck(ctx); err != nil {
        return fmt.Errorf("db unhealthy: %w", err)
    }
    return err
}
Defensive patterns

Strategy: retry

Validate before calling

// verify DB reachable before pushing alerts
if err := c.Ent.Schema.Create(ctx) /* or a trivial query */; err != nil { return err }
if alertItem.UUID == "" { return errors.New("pre-check: alert UUID is empty") }

Try / catch

id, err := client.CreateOrUpdateAlert(ctx, machineID, alert)
if err != nil && strings.HasPrefix(err.Error(), "unable to query alerts") {
    // DB-level failure, not 'not found': retry after health check
    if isDbHealthy(ctx) { id, err = client.CreateOrUpdateAlert(ctx, machineID, alert) }
}

Prevention

When it happens

Trigger: c.Ent.Alert.Query().Where(alert.UUID(...)).WithDecisions().All(ctx) returns a non-NotFound error: DB connection failure, SQLite lock/timeout, corrupted schema, or context cancellation during the PAPI AlertCmd flow.

Common situations: SQLite file locked by another crowdsec process; database migrated to a schema the binary doesn't understand after upgrade; DB unreachable (remote PostgreSQL/MySQL down); context deadline exceeded on a slow disk.

Understand the failure class

Background: Database query failed: Internal Server Error 500s wrapping SQL, Prisma, and connection failures — what to check first — this error's family across 16 libraries.

Related errors


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