crowdsecurity/crowdsec · error

empty time now() - %s

Error message

empty time now() - %s

What it means

Returned by handleTimeFilters when time.Now().UTC().Add(-duration) yields the zero time value. This is a defensive check; with real clock values it is practically unreachable but signals that the computed time point is unusable for a GTE/LTE predicate.

Source

Thrown at pkg/database/alertfilter.go:54

		scope = types.Ip
	} else if strings.ToLower(scope) == "range" {
		scope = types.Range
	}

	*predicates = append(*predicates, alert.SourceScopeEQ(scope))
}

func handleTimeFilters(param, value string, predicates *[]predicate.Alert) error {
	// crowsdec now always sends duration without days, but we allow them for
	// compatibility with other tools
	duration, err := cstime.ParseDurationWithDays(value)
	if err != nil {
		return fmt.Errorf("while parsing duration: %w", err)
	}

	timePoint := time.Now().UTC().Add(-duration)
	if timePoint.IsZero() {
		return fmt.Errorf("empty time now() - %s", timePoint.String())
	}

	switch param {
	case "since":
		*predicates = append(*predicates, alert.StartedAtGTE(timePoint))
	case "created_before":
		*predicates = append(*predicates, alert.CreatedAtLTE(timePoint))
	case "until":
		*predicates = append(*predicates, alert.StartedAtLTE(timePoint))
	}

	return nil
}

func handleAlertIPv4Predicates(rng csnet.Range, contains bool, predicates *[]predicate.Alert) {
	if contains { // decision contains {start_ip,end_ip}
		*predicates = append(*predicates, alert.And(
			alert.HasDecisionsWith(decision.StartIPLTE(rng.Start.Addr)),

View on GitHub (pinned to 909b515798)

Solutions

  1. Verify system clock is sane (date; timedatectl) — an absurdly wrong clock is the realistic trigger.
  2. Remove any test/mocked clock returning zero time.Time{} and inject a realistic one.
  3. Update crowdsec, as newer versions may have dropped or refined this check.
Defensive patterns

Strategy: try-catch

Validate before calling

if time.Now().IsZero() {
    return fmt.Errorf("system clock reports zero time; refusing to build filter")
}

Try / catch

preds, err := alertPredicatesFromFilter(filter)
if err != nil {
    log.Warnf("time filter rejected: %v", err)
    return http.StatusBadRequest
}

Prevention

When it happens

Trigger: The computed timePoint from now minus the parsed duration equals time.Time{} — only possible in degenerate conditions (clock anomalies, mocked zero clocks in tests).

Common situations: Test environments with a zero-valued mocked clock, or exotic time sources returning the zero time.

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


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