{"record":{"id":"0686b2807ddea0c2","repo":"App-vNext/Polly","slug":"the-delegate-executed-asynchronously-through-timeo","errorCode":null,"errorMessage":"The delegate executed asynchronously through TimeoutPolicy did not complete within the timeout.","messagePattern":"The delegate executed asynchronously through TimeoutPolicy did not complete within the timeout\\.","errorType":"exception","errorClass":"TimeoutRejectedException","httpStatus":null,"severity":"error","filePath":"src/Polly/Timeout/AsyncTimeoutEngine.cs","lineNumber":49,"sourceCode":"\n            // else: timeoutStrategy == TimeoutStrategy.Pessimistic\n\n            Task<TResult> timeoutTask = timeoutCancellationTokenSource.Token.AsTask<TResult>();\n\n            SystemClock.CancelTokenAfter(timeoutCancellationTokenSource, timeout);\n\n            actionTask = action(context, combinedToken);\n\n            return await (await Task.WhenAny(actionTask, timeoutTask).ConfigureAwait(continueOnCapturedContext)).ConfigureAwait(continueOnCapturedContext);\n        }\n        catch (Exception ex)\n        {\n            // Note that we cannot rely on testing (operationCanceledException.CancellationToken == combinedToken || operationCanceledException.CancellationToken == timeoutCancellationTokenSource.Token)\n            // as either of those tokens could have been onward combined with another token by executed code, and so may not be the token expressed on operationCanceledException.CancellationToken.\n            if (ex is OperationCanceledException && timeoutCancellationTokenSource.IsCancellationRequested)\n            {\n                await onTimeoutAsync(context, timeout, actionTask, ex).ConfigureAwait(continueOnCapturedContext);\n                throw new TimeoutRejectedException(\"The delegate executed asynchronously through TimeoutPolicy did not complete within the timeout.\", timeout, ex);\n            }\n\n            throw;\n        }\n        finally\n        {\n            // If timeoutCancellationTokenSource was canceled & our combined token hasn't been signaled, cancel it.\n            // This avoids the exception propagating before the linked token can signal the downstream to cancel.\n            // See https://github.com/App-vNext/Polly/issues/722.\n            // stryker disable once all : no means to test this\n            if (!combinedTokenSource.IsCancellationRequested && timeoutCancellationTokenSource.IsCancellationRequested)\n            {\n#if NET8_0_OR_GREATER\n                await combinedTokenSource.CancelAsync().ConfigureAwait(false);\n#else\n                combinedTokenSource.Cancel();\n#endif\n            }","sourceCodeStart":31,"sourceCodeEnd":67,"githubUrl":"https://github.com/App-vNext/Polly/blob/d0e46bdb1ee11ea50d0e4b6846d2633d6bc09bac/src/Polly/Timeout/AsyncTimeoutEngine.cs#L31-L67","documentation":"TimeoutRejectedException is the runtime signal that the executed delegate did not finish within the configured timeout. AsyncTimeoutEngine throws it (AsyncTimeoutEngine.cs:49) only when an OperationCanceledException coincides with the internal timeout token being cancelled — i.e. the policy's own timeout fired, not the caller's cancellation. The wrapped exception is the original OperationCanceledException and the Timeout property carries the configured TimeSpan.","triggerScenarios":"Executing a delegate through an AsyncTimeoutPolicy whose action takes longer than the configured timeout (optimistic: the action ignores the CancellationToken; pessimistic: the action runs past the deadline). The engine detects timeoutCancellationTokenSource.IsCancellationRequested inside the OperationCanceledException handler and converts it to TimeoutRejectedException.","commonSituations":"An HTTP call or DB query that stalls and exceeds the timeout; an optimistic timeout where the downstream code does not honour the CancellationToken; a timeout value set too low for normal latency; network degradation or a slow dependency under load; deadlocks in the executed delegate.","solutions":["Catch TimeoutRejectedException specifically and apply your fallback (cached value, default, or rethrow to a higher-level handler).","Increase the configured timeout to a realistic value for the operation's p99 latency.","If using optimistic timeout, ensure the executed delegate observes and responds to the CancellationToken it receives.","For stubborn non-cancellable calls, switch to TimeoutStrategy.Pessimistic so the policy does not rely on cooperative cancellation.","Wrap the timeout policy in a retry or fallback policy to recover gracefully."],"exampleFix":"// before\nvar policy = Policy.TimeoutAsync(2, TimeoutStrategy.Optimistic);\nawait policy.ExecuteAsync(ct => httpClient.GetStringAsync(url), CancellationToken.None);\n// throws TimeoutRejectedException when the call exceeds 2s\n\n// after\nvar timeout = Policy.TimeoutAsync(10, TimeoutStrategy.Pessimistic);\nvar fallback = Policy<object>\n    .Handle<TimeoutRejectedException>()\n    .FallbackAsync(_ => Task.FromResult<object>(defaultValue));\nvar wrapped = fallback.WrapAsync(timeout);\nawait wrapped.ExecuteAsync(ct => httpClient.GetStringAsync(url, ct), CancellationToken.None);","handlingStrategy":"try-catch","validationCode":null,"typeGuard":"static bool IsTimeoutRejected(Exception ex) => ex is TimeoutRejectedException;","tryCatchPattern":"try\n{\n    await timeoutPolicy.ExecuteAsync(ct => DoWorkAsync(ct), CancellationToken.None);\n}\ncatch (TimeoutRejectedException ex)\n{\n    logger.LogWarning(ex, \"Operation timed out after {Timeout}\", ex.Timeout);\n    return fallbackValue; // or rethrow to a higher-level handler\n}","preventionTips":["Tune the timeout to the operation's realistic p99 latency plus headroom; a too-small timeout causes chronic TimeoutRejectedException.","For optimistic timeout, ensure the executed delegate honours the CancellationToken it receives so cancellation is cooperative.","Wrap the timeout policy in a fallback or retry policy so a timeout degrades gracefully instead of surfacing as an error.","Use TimeoutStrategy.Pessimistic for non-cancellable work so the policy is not dependent on cooperative cancellation.","Log ex.Timeout from the exception to confirm the configured deadline vs the actual failure."],"tags":["timeoutrejectedexception","timeout","runtime","cancellation","async","polly"],"backgroundTag":null,"analyzedSha":"d0e46bdb1ee11ea50d0e4b6846d2633d6bc09bac","analyzedAt":"2026-08-13T16:36:01.959Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}