istio/istio · error

HTTP route rule cannot contain both direct_response and redi

Error message

HTTP route rule cannot contain both direct_response and redirect

What it means

Both 'direct_response' and 'redirect' are terminal actions — one returns a fixed response locally, the other instructs the client to go elsewhere. Setting both on a single http route is ambiguous and rejected by validation.

Source

Thrown at pkg/config/validation/virtualservice.go:224

		}
	}

	// check for conflicts
	if http.Redirect != nil {
		if len(http.Route) > 0 {
			errs = appendErrors(errs, errors.New("HTTP route cannot contain both route and redirect"))
		}

		if http.Fault != nil {
			errs = appendErrors(errs, errors.New("HTTP route cannot contain both fault and redirect"))
		}

		if http.Rewrite != nil {
			errs = appendErrors(errs, errors.New("HTTP route rule cannot contain both rewrite and redirect"))
		}

		if http.DirectResponse != nil {
			errs = appendErrors(errs, errors.New("HTTP route rule cannot contain both direct_response and redirect"))
		}
	} else if http.DirectResponse != nil {
		if len(http.Route) > 0 {
			errs = appendErrors(errs, errors.New("HTTP route cannot contain both route and direct_response"))
		}

		if http.Fault != nil {
			errs = appendErrors(errs, errors.New("HTTP route cannot contain both fault and direct_response"))
		}

		if http.Rewrite != nil {
			errs = appendErrors(errs, errors.New("HTTP route rule cannot contain both rewrite and direct_response"))
		}

		if http.Redirect != nil {
			errs = appendErrors(errs, errors.New("HTTP route rule cannot contain both redirect and direct_response"))
		}
	} else if len(http.Route) == 0 {

View on GitHub (pinned to 8dc789c5cf)

Solutions

  1. Keep 'directResponse' if a local fixed response is wanted; remove 'redirect'
  2. Keep 'redirect' if the client should be sent elsewhere; remove 'directResponse'
  3. Use match conditions to split the behaviors across two routes if both are needed

Example fix

# before
http:
- match: [{uri: {prefix: /gone}}]
  directResponse: {status: 410}
  redirect: {uri: /}

# after
http:
- match: [{uri: {prefix: /gone}}]
  directResponse: {status: 410}
Defensive patterns

Strategy: validation

Validate before calling

func directResponseAndRedirectCompatible(http *networking.HTTPRoute) bool {
	return !(http.GetDirectResponse() != nil && http.GetRedirect() != nil)
}

Type guard

func hasDirectResponseRedirectConflict(http *networking.HTTPRoute) bool {
	return http.GetDirectResponse() != nil && http.GetRedirect() != nil
}

Prevention

When it happens

Trigger: An http route containing both 'directResponse:' (status/body) and 'redirect:'.

Common situations: A/B testing config or migration from returning a static error page to redirecting, with the old block left behind.

Related errors


AI-assisted analysis of istio/istio@8dc789c5cf (2026-08-15). Data as JSON: /api/errors/c2ce7e005cb541c0. Report an issue: GitHub.