SigNoz/signoz · error

not a valid TTL duration %v

Error message

not a valid TTL duration %v

What it means

The 'duration' query parameter must be a valid Go duration string parseable by time.ParseDuration with a positive value (seconds > 0). Zero, negative, or malformed durations are rejected before the TTL is applied.

Source

Thrown at pkg/query-service/app/parser.go:443

	// make sure either of the query params are present
	typeTTL := r.URL.Query().Get("type")
	delDuration := r.URL.Query().Get("duration")
	coldStorage := r.URL.Query().Get("coldStorage")
	toColdDuration := r.URL.Query().Get("toColdDuration")

	if len(typeTTL) == 0 || len(delDuration) == 0 {
		return nil, fmt.Errorf("type and duration param cannot be empty from the query")
	}

	// Validate the type parameter
	if typeTTL != retentiontypes.TraceTTL && typeTTL != retentiontypes.MetricsTTL && typeTTL != retentiontypes.LogsTTL {
		return nil, fmt.Errorf("type param should be metrics|traces|logs, got %v", typeTTL)
	}

	// Validate the TTL duration.
	durationParsed, err := time.ParseDuration(delDuration)
	if err != nil || durationParsed.Seconds() <= 0 {
		return nil, fmt.Errorf("not a valid TTL duration %v", delDuration)
	}

	var toColdParsed time.Duration

	// If some cold storage is provided, validate the cold storage move TTL.
	if len(coldStorage) > 0 {
		toColdParsed, err = time.ParseDuration(toColdDuration)
		if err != nil || toColdParsed.Seconds() <= 0 {
			return nil, fmt.Errorf("not a valid toCold TTL duration %v", toColdDuration)
		}
		if toColdParsed.Seconds() != 0 && toColdParsed.Seconds() >= durationParsed.Seconds() {
			return nil, fmt.Errorf("delete TTL should be greater than cold storage move TTL")
		}
	}

	return &retentiontypes.TTLParams{
		Type:                  typeTTL,
		DelDuration:           int64(durationParsed.Seconds()),

View on GitHub (pinned to 5069bf80b0)

Solutions

  1. Use Go duration syntax with a unit, e.g. duration=72h or duration=48h0m0s
  2. Ensure the value is strictly positive
  3. If sending from code, format with time.Duration.String()

Example fix

// before
?type=traces&duration=72
// after
?type=traces&duration=72h
Defensive patterns

Strategy: validation

Validate before calling

d, err := time.ParseDuration(durationStr)
if err != nil || d <= 0 { return fmt.Errorf("duration must be a positive Go duration like 72h") }

Prevention

When it happens

Trigger: Passing duration=0, duration=-24h, duration=72 (bare number, no unit), or duration=forever to setTTL.

Common situations: Passing a plain number of hours instead of a Go duration string; sending milliseconds as '72000' without a unit; frontend sending seconds as an integer.

Related errors


AI-assisted analysis of SigNoz/signoz@5069bf80b0 (2026-08-28). Data as JSON: /api/errors/1248d32975db0733. Report an issue: GitHub.