{"record":{"id":"63af7c4611bf6386","repo":"App-vNext/Polly","slug":"ontimeoutasync","errorCode":null,"errorMessage":"onTimeoutAsync","messagePattern":"onTimeoutAsync","errorType":"exception","errorClass":"ArgumentNullException","httpStatus":null,"severity":"error","filePath":"src/Polly/Timeout/AsyncTimeoutSyntax.cs","lineNumber":360,"sourceCode":"    /// <exception cref=\"ArgumentNullException\">Thrown when <paramref name=\"onTimeoutAsync\"/> is <see langword=\"null\"/>.</exception>\n    public static AsyncTimeoutPolicy TimeoutAsync(Func<Context, TimeSpan> timeoutProvider, Func<Context, TimeSpan, Task, Exception, Task> onTimeoutAsync) =>\n        TimeoutAsync(timeoutProvider, TimeoutStrategy.Optimistic, onTimeoutAsync);\n\n    /// <summary>\n    /// Builds an <see cref=\"AsyncPolicy\" /> that will wait asynchronously for a delegate to complete for a specified period of time. A <see cref=\"TimeoutRejectedException\" /> will be thrown if the delegate does not complete within the configured timeout.\n    /// </summary>\n    /// <param name=\"timeoutProvider\">A function to provide the timeout for this execution.</param>\n    /// <param name=\"timeoutStrategy\">The timeout strategy.</param>\n    /// <param name=\"onTimeoutAsync\">An action to call on timeout, passing the execution context, the timeout applied, and a <see cref=\"Task\" /> capturing the abandoned, timed-out action.\n    /// <remarks>The Task parameter will be null if the executed action responded cooperatively to cancellation before the policy timed it out.</remarks></param>\n    /// <returns>The policy instance.</returns>\n    /// <exception cref=\"ArgumentNullException\">Thrown when <paramref name=\"timeoutProvider\"/> is <see langword=\"null\"/>.</exception>\n    /// <exception cref=\"ArgumentNullException\">Thrown when <paramref name=\"onTimeoutAsync\"/> is <see langword=\"null\"/>.</exception>\n    public static AsyncTimeoutPolicy TimeoutAsync(Func<Context, TimeSpan> timeoutProvider, TimeoutStrategy timeoutStrategy, Func<Context, TimeSpan, Task, Task> onTimeoutAsync)\n    {\n        if (onTimeoutAsync == null)\n        {\n            throw new ArgumentNullException(nameof(onTimeoutAsync));\n        }\n\n        return TimeoutAsync(timeoutProvider, timeoutStrategy, (ctx, timeout, task, _) => onTimeoutAsync(ctx, timeout, task));\n    }\n\n    /// <summary>\n    /// Builds an <see cref=\"AsyncPolicy\" /> that will wait asynchronously for a delegate to complete for a specified period of time. A <see cref=\"TimeoutRejectedException\" /> will be thrown if the delegate does not complete within the configured timeout.\n    /// </summary>\n    /// <param name=\"timeoutProvider\">A function to provide the timeout for this execution.</param>\n    /// <param name=\"timeoutStrategy\">The timeout strategy.</param>\n    /// <param name=\"onTimeoutAsync\">An action to call on timeout, passing the execution context, the timeout applied, the <see cref=\"Task\" /> capturing the abandoned, timed-out action, and the captured <see cref=\"Exception\"/>.\n    /// <remarks>The Task parameter will be null if the executed action responded cooperatively to cancellation before the policy timed it out.</remarks></param>\n    /// <returns>The policy instance.</returns>\n    /// <exception cref=\"ArgumentNullException\">Thrown when <paramref name=\"timeoutProvider\"/> is <see langword=\"null\"/>.</exception>\n    /// <exception cref=\"ArgumentNullException\">Thrown when <paramref name=\"onTimeoutAsync\"/> is <see langword=\"null\"/>.</exception>\n    public static AsyncTimeoutPolicy TimeoutAsync(\n        Func<Context, TimeSpan> timeoutProvider,\n        TimeoutStrategy timeoutStrategy,","sourceCodeStart":342,"sourceCodeEnd":378,"githubUrl":"https://github.com/App-vNext/Polly/blob/d0e46bdb1ee11ea50d0e4b6846d2633d6bc09bac/src/Polly/Timeout/AsyncTimeoutSyntax.cs#L342-L378","documentation":"Thrown by the legacy Polly TimeoutAsync overload that accepts a 3-argument onTimeoutAsync callback (Context, TimeSpan, Task). The method guards its onTimeoutAsync parameter with ArgumentNullException at the very top, before delegating to the 4-argument overload. This is a construction-time validation, not a runtime timeout error — the policy is never created when the timeout callback is null.","triggerScenarios":"Calling Policy.TimeoutAsync(timeoutProvider, timeoutStrategy, null) where the third argument (the Func<Context, TimeSpan, Task, Task> onTimeoutAsync) is null. Also triggered when a variable holding the callback was never assigned or was conditionally set to null.","commonSituations":"Refactoring code where the onTimeout callback was previously inlined and later extracted into a nullable field; DI containers injecting an unset callback; copy-paste from a simpler overload that omits the callback.","solutions":["Pass a non-null Func<Context, TimeSpan, Task, Task>, e.g. an inline lambda (_, __, ___) => Task.CompletedTask if you have no work to do on timeout.","If you do not need a timeout callback at all, call the 2-argument overload TimeoutAsync(timeoutProvider, timeoutStrategy) which wires an empty default handler.","Trace where the null value originates (DI registration, optional parameter, uninitialized field) and fix the assignment at the source."],"exampleFix":"// before\nPolicy.TimeoutAsync(provider, TimeoutStrategy.Optimistic, null);\n\n// after\nPolicy.TimeoutAsync(provider, TimeoutStrategy.Optimistic, (ctx, ts, task) => Task.CompletedTask);","handlingStrategy":"validation","validationCode":"if (onTimeoutAsync is null) throw new ArgumentException(\"onTimeoutAsync must be supplied\", nameof(onTimeoutAsync));\nvar policy = Policy.TimeoutAsync(provider, TimeoutStrategy.Optimistic, onTimeoutAsync);","typeGuard":"static bool HasTimeoutHandler(Func<Context, TimeSpan, Task, Task> cb) => cb is not null;","tryCatchPattern":null,"preventionTips":["Prefer the overload that omits the callback when you have nothing to do on timeout.","Treat null callbacks as a configuration error and fail at startup, not at policy construction.","Use C# 8+ nullable reference types so the compiler rejects passing null."],"tags":["argument-null","validation","timeout","legacy-api","polly-v7"],"backgroundTag":null,"analyzedSha":"d0e46bdb1ee11ea50d0e4b6846d2633d6bc09bac","analyzedAt":"2026-08-13T16:36:01.959Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}