dotnet/yarp · critical · InvalidOperationException
The timeout was not applied for route '{route.Config.RouteId
Error message
The timeout was not applied for route '{route.Config.RouteId}', ensure `IApplicationBuilder.UseRequestTimeouts()` is called between `IApplicationBuilder.UseRouting()` and `IApplicationBuilder.UseEndpoints()`. What it means
When a route has a `RequestTimeoutAttribute` in its endpoint metadata but no `IHttpRequestTimeoutFeature` is present on the HttpContext, it means the ASP.NET Core request timeouts middleware (`UseRequestTimeouts`) did not run or was placed incorrectly. YARP detects this mismatch and throws rather than silently allowing a request to proceed without its configured timeout — a safety-first design choice. The check is skipped when a debugger is attached to allow debugging.
Source
Thrown at src/ReverseProxy/Model/ProxyPipelineInitializerMiddleware.cs:108
context.Features.Get<IHttpRequestTimeoutFeature>() is null &&
// The feature is skipped if the request is already canceled. We'll handle canceled requests later for consistency.
!context.RequestAborted.IsCancellationRequested &&
// The policy may set the timeout to null / infinite.
TimeoutPolicyRequestedATimeoutBeSet(requestTimeout))
{
// A timeout should have been set.
// Out of an abundance of caution, refuse the request rather than allowing it to proceed without the configured timeout.
ThrowIfDebuggerNotAttached(route);
}
void ThrowIfDebuggerNotAttached(RouteModel route)
{
// The feature is skipped if the debugger is attached.
if (!Debugger.IsAttached)
{
Log.TimeoutNotApplied(_logger, route.Config.RouteId);
throw new InvalidOperationException(
$"The timeout was not applied for route '{route.Config.RouteId}', " +
"ensure `IApplicationBuilder.UseRequestTimeouts()` is called between " +
"`IApplicationBuilder.UseRouting()` and `IApplicationBuilder.UseEndpoints()`.");
}
}
}
private bool TimeoutPolicyRequestedATimeoutBeSet(RequestTimeoutAttribute requestTimeout)
{
if (requestTimeout.Timeout is not TimeSpan timeout)
{
if (requestTimeout.PolicyName is not string policyName)
{
Debug.Fail("Either Timeout or PolicyName should have been set.");
return false;
}
if (!_timeoutOptions.CurrentValue.Policies.TryGetValue(policyName, out var policy))View on GitHub (pinned to bd11867bee)
Solutions
- Add `app.UseRequestTimeouts()` between `app.UseRouting()` and `app.UseEndpoints(...)` (or `app.MapReverseProxy()`) in Program.cs.
- Verify the ordering: `UseRouting` → `UseRequestTimeouts` → `UseEndpoints`/`MapReverseProxy`. If any are swapped, the timeout feature won't be set.
- If you don't want YARP to enforce request timeouts, remove the timeout configuration from the route/cluster config so no `RequestTimeoutAttribute` is attached.
- During local debugging, note that the throw is suppressed when a debugger is attached — so this may only reproduce in deployed environments.
Example fix
// before — UseRequestTimeouts missing var app = builder.Build(); app.UseRouting(); app.MapReverseProxy(); // throws if route has timeout config app.Run(); // after — correct middleware ordering var app = builder.Build(); app.UseRouting(); app.UseRequestTimeouts(); app.MapReverseProxy(); app.Run();
Defensive patterns
Strategy: validation
Validate before calling
// At startup, verify the middleware pipeline ordering // This is a code-structure assertion, not runtime: /* Correct order: app.UseRouting(); app.UseRequestTimeouts(); app.MapReverseProxy(); */ // If timeouts are not configured on any route, UseRequestTimeouts is not needed.
Type guard
// No type guard — this is a middleware-ordering configuration issue.
Try / catch
// Not recommended — this is a fail-fast safety check by design. // Fix the middleware ordering instead of catching the exception.
Prevention
- If any route has a timeout policy, always add app.UseRequestTimeouts() between UseRouting and MapReverseProxy.
- Use the YARP Program.cs template as a reference for correct ordering.
- Remember that the throw is suppressed when a debugger is attached — test in a non-debug build too.
When it happens
Trigger: A YARP route is configured with a timeout policy (`RequestTimeout` or a named timeout policy in the route config). The `RequestTimeoutAttribute` metadata is set on the endpoint. However, `IHttpRequestTimeoutFeature` is null because `app.UseRequestTimeouts()` was not called, or was called in the wrong position (not between `UseRouting()` and `UseEndpoints()`). The `EnsureRequestTimeoutPolicyIsAppliedCorrectly` method detects the missing feature and throws (unless a debugger is attached).
Common situations: A developer configures timeouts in the YARP config (`HttpRequest.ActivityTimeout` or timeout policies) but forgets to add `app.UseRequestTimeouts()` in Program.cs. The middleware is added but in the wrong order (after `UseEndpoints`, or before `UseRouting`). A framework upgrade changed where `UseRequestTimeouts` must be placed.
Understand the failure class
- Timeouts: ETIMEDOUT, deadlines, and hung requests — what actually expires when a request times out.
Related errors
- The {typeof(IReverseProxyFeature).FullName} is missing the {
- {typeof(IReverseProxyFeature).FullName} is missing.
- Routing Endpoint wasn't set for the current request.
- Configuration Filter Error: Substitution for '{lookup}' in c
- A non-empty CustomTransform value is required
AI-assisted analysis of dotnet/yarp@bd11867bee (2026-08-13).
Data as JSON: /api/errors/538571b40dcd8962.
Report an issue: GitHub.