crowdsecurity/crowdsec · warning · InvalidFilter

invalid id_gt value: %w: %w

Error message

invalid id_gt value: %w: %w

What it means

applyDecisionFilter rejects the request because the 'id_gt' (id greater-than) query parameter is not a valid integer (strconv.Atoi fails). This filter is used for keyset-style pagination of decisions; wrapped with the InvalidFilter sentinel.

Source

Thrown at pkg/database/decisionfilter.go:99

			}
		case "limit":
			limit, err := strconv.Atoi(value[0])
			if err != nil {
				return nil, fmt.Errorf("invalid limit value: %w: %w", err, InvalidFilter)
			}

			query = query.Limit(limit)
		case "offset":
			offset, err := strconv.Atoi(value[0])
			if err != nil {
				return nil, fmt.Errorf("invalid offset value: %w: %w", err, InvalidFilter)
			}

			query = query.Offset(offset)
		case "id_gt":
			id, err := strconv.Atoi(value[0])
			if err != nil {
				return nil, fmt.Errorf("invalid id_gt value: %w: %w", err, InvalidFilter)
			}

			query = query.Where(decision.IDGT(id))
		}
	}

	query, err = decisionIPFilter(query, contains, rng)
	if err != nil {
		return nil, fmt.Errorf("fail to apply StartIpEndIpFilter: %w", err)
	}

	return query, nil
}

func decisionIPv4Filter(decisions *ent.DecisionQuery, contains bool, rng csnet.Range) (*ent.DecisionQuery, error) {
	if contains {
		// Decision contains {start_ip,end_ip}
		return decisions.Where(decision.And(

View on GitHub (pinned to 909b515798)

Solutions

  1. Send the numeric decision ID as an integer (e.g. ?id_gt=12345).
  2. Use the numeric 'id' field from the previous page's last decision, not its UUID.
  3. Omit id_gt when not using keyset pagination.
  4. Cast/validate the stored last-id to int before constructing the query.

Example fix

// before
GET /v1/decisions?id_gt=abc-uuid-123
// after
GET /v1/decisions?id_gt=12345
Defensive patterns

Strategy: validation

Validate before calling

lastID, err := strconv.Atoi(storedLastID)
if err != nil {
    return fmt.Errorf("corrupt cursor %q: %w", storedLastID, err)
}
// then pass lastID as id_gt

Try / catch

resp, err := lapi.GetDecisions(ctx, models.GetDecisionsOpts{IDGt: &lastID})
if err != nil && strings.Contains(err.Error(), "invalid id_gt value") {
    return fmt.Errorf("reset pagination cursor, %q is not an int", storedLastID)
}

Prevention

When it happens

Trigger: GET /v1/decisions?id_gt=last or ?id_gt=0.5 on decisions endpoints; also negative values will parse but may be unexpected.

Common situations: Clients tracking 'last seen id' whose stored value got corrupted or truncated; passing a decision UUID instead of the numeric ID.

Understand the failure class

Background: "Invalid query parameter" / "Failed to parse value of ...": fixing bad query string parameters across APIs — this error's family across 36 libraries.

Related errors


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