istio/istio · error · ConfigError
TranslationError
TranslationError
Error message
failed to parse request timeout: %w
What it means
ApplyTimeouts parses HTTPRouteRule.spec.timeouts.request (a GEP-2257 duration string) with Go's time.ParseDuration. Strings Go cannot parse — missing unit ('30'), unknown unit ('1sec'), embedded spaces ('1 h'), or garbage — return this wrapped error, which ConvertHTTPRouteToAgw surfaces as a TranslationError condition on the route. Note Go is more permissive than GEP-2257 (it accepts '1m30s', '1.5h'), so values that parse here but violate GEP-2257 are accepted, while anything Go rejects fails.
Source
Thrown at pilot/pkg/config/kube/agentgateway/routes.go:125
})
}
return nil
}
// ApplyTimeouts applies timeouts to an agw route
func ApplyTimeouts(rule *gatewayv1.HTTPRouteRule, route *api.Route) error {
if rule == nil || rule.Timeouts == nil {
return nil
}
if route.TrafficPolicies == nil {
route.TrafficPolicies = []*api.TrafficPolicySpec{}
}
var reqDur, beDur *durationpb.Duration
if rule.Timeouts.Request != nil {
d, err := time.ParseDuration(string(*rule.Timeouts.Request))
if err != nil {
return fmt.Errorf("failed to parse request timeout: %w", err)
}
if d != 0 {
// "Setting a timeout to the zero duration (e.g. "0s") SHOULD disable the timeout"
// However, agentgateway already defaults to no timeout, so only set for non-zero
reqDur = durationpb.New(d)
}
}
if rule.Timeouts.BackendRequest != nil {
d, err := time.ParseDuration(string(*rule.Timeouts.BackendRequest))
if err != nil {
return fmt.Errorf("failed to parse backend request timeout: %w", err)
}
if d != 0 {
// "Setting a timeout to the zero duration (e.g. "0s") SHOULD disable the timeout"
// However, agentgateway already defaults to no timeout, so only set for non-zero
beDur = durationpb.New(d)
}
}View on GitHub (pinned to 8dc789c5cf)
Solutions
- Use a valid duration with an explicit unit: '10s', '1m', '500ms', '1.5h'
- If the value comes from templating, ensure the unit is part of the template, not the variable: timeout: "{{ .timeoutSeconds }}s"
- Apply routes with server-side dry-run so the CRD pattern catches malformed durations before istiod translates them
Example fix
# before
spec:
rules:
- timeouts:
request: 30
# after
spec:
rules:
- timeouts:
request: 30s Defensive patterns
Strategy: validation
Validate before calling
if rule.Timeouts != nil && rule.Timeouts.Request != nil {
if _, err := time.ParseDuration(string(*rule.Timeouts.Request)); err != nil {
return fmt.Errorf("timeouts.request %q is not a valid duration (use e.g. \"10s\", \"1m\"): %w", *rule.Timeouts.Request, err)
}
} Type guard
func isParseableGEPDuration(s string) bool {
_, err := time.ParseDuration(s)
return err == nil
} Try / catch
if err := agentgateway.ApplyTimeouts(&rule, route); err != nil {
if strings.Contains(err.Error(), "request timeout") {
// reject/fix the manifest: timeouts.request is not a valid duration
}
return err // propagate as TranslationError on the route status
} Prevention
- Always include a unit suffix; when injecting numeric values from templates append a literal 's'
- Use Go durations or GEP-2257 examples ('30s', '1m', '500ms') — never ISO-8601 ('PT30S') or bare numbers
- Validate generated HTTPRoutes with kubectl apply --dry-run=server so the CRD pattern rejects bad durations early
When it happens
Trigger: An HTTPRoute rule with timeouts.request set to a non-Go-duration string, e.g. "30", "1sec", "second", "1 h", "PT30S" (ISO-8601 by mistake), or "500ms...". The v1 CRD pattern normally rejects these at admission, so hitting this means the route was created programmatically or with relaxed CRDs.
Common situations: Pasting ISO-8601 durations from other systems; numeric-only values from templating ({{ .timeout }} without a unit suffix); generated routes from internal platforms; hand-built HTTPRoute structs in Go.
Understand the failure class
- Timeouts: ETIMEDOUT, deadlines, and hung requests — what actually expires when a request times out.
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- path match Error: %v
- headers match Error: %v
- method match Error: %v
- query match Error: %v
- http_idle_timeout must be non-negative
AI-assisted analysis of istio/istio@8dc789c5cf (2026-08-15).
Data as JSON: /api/errors/4e0e5f450ce5444c.
Report an issue: GitHub.