grpc/grpc-go · error

rls: failed to parse max_age in route lookup config %+v: %v

Error message

rls: failed to parse max_age in route lookup config %+v: %v

What it means

Returned by parseRLSProto (config.go:227-230) when convertDuration fails on RouteLookupConfig.max_age for the same reason as the timeout: the google.protobuf.Duration is out of range (durationpb.CheckValid rejects invalid seconds/nanos). Note valid values are capped to 5 minutes (maxMaxAge) after parsing.

Source

Thrown at balancer/rls/config.go:229

	}

	lookupServiceTimeout, err := convertDuration(rlsProto.GetLookupServiceTimeout())
	if err != nil {
		return nil, fmt.Errorf("rls: failed to parse lookup_service_timeout in route lookup config %+v: %v", rlsProto, err)
	}
	if lookupServiceTimeout == 0 {
		lookupServiceTimeout = defaultLookupServiceTimeout
	}

	// Validations performed here:
	// - if `max_age` > 5m, it should be set to 5 minutes
	//   only if stale age is not set
	// - if `stale_age` > `max_age`, ignore it
	// - if `stale_age` is set, then `max_age` must also be set
	maxAgeSet := false
	maxAge, err := convertDuration(rlsProto.GetMaxAge())
	if err != nil {
		return nil, fmt.Errorf("rls: failed to parse max_age in route lookup config %+v: %v", rlsProto, err)
	}
	if maxAge == 0 {
		maxAge = maxMaxAge
	} else {
		maxAgeSet = true
	}

	staleAgeSet := false
	staleAge, err := convertDuration(rlsProto.GetStaleAge())
	if err != nil {
		return nil, fmt.Errorf("rls: failed to parse staleAge in route lookup config %+v: %v", rlsProto, err)
	}
	if staleAge == 0 {
		staleAge = maxMaxAge
	} else {
		staleAgeSet = true
	}

View on GitHub (pinned to 03255a9237)

Solutions

  1. Provide a sane max_age (0 to use the 5-minute default, or <= 5m); the policy caps it at 5 minutes anyway.
  2. Build the Duration with durationpb.New(time.Duration) to guarantee validity.
  3. Check the control plane's max_age generation.

Example fix

// before
rlc.MaxAge = &durationpb.Duration{ Seconds: -1, Nanos: -1000000000 } // invalid nanos

// after
rlc.MaxAge = durationpb.New(5 * time.Minute)
Defensive patterns

Strategy: validation

Validate before calling

func validateMaxAge(d *durationpb.Duration) error {
    if d == nil { return nil }
    return d.CheckValid()
}

Prevention

When it happens

Trigger: max_age Duration proto is structurally invalid (out-of-range seconds or nanos). A value of 0 is valid (defaults to 5m); only structurally invalid Durations trigger this.

Common situations: Control-plane overflow building the Duration. Manually setting Nanos out of [-1e9,1e9).

Understand the failure class

Related errors


AI-assisted analysis of grpc/grpc-go@03255a9237 (2026-08-07). Data as JSON: /api/errors/a6bd2e4f62b0ff2a. Report an issue: GitHub.