Skip to content

Use descriptive ErrorMessage for timed out requests#2356

Merged
alexeyzimarev merged 1 commit intodevfrom
fix/timeout-error-message
Feb 26, 2026
Merged

Use descriptive ErrorMessage for timed out requests#2356
alexeyzimarev merged 1 commit intodevfrom
fix/timeout-error-message

Conversation

@alexeyzimarev
Copy link
Member

Summary

  • When a request times out, ErrorMessage now says "The request timed out." instead of "A task was canceled."
  • ErrorException still holds the original TaskCanceledException unchanged
  • All three state properties are now consistent: ResponseStatus.TimedOut + meaningful ErrorMessage + original ErrorException
  • Non-timeout errors (aborted, network errors, etc.) are unaffected

Fixes #2257

Test plan

  • Project builds successfully
  • All existing unit tests pass
  • No existing tests assert on ErrorMessage string content for timeout cases

🤖 Generated with Claude Code

When a request times out, ErrorMessage was set to the TaskCanceledException
message ("A task was canceled.") which contradicts ResponseStatus.TimedOut.
Now ErrorMessage says "The request timed out." for timeout scenarios, keeping
all three state properties (ResponseStatus, ErrorMessage, ErrorException)
consistent. ErrorException still holds the original TaskCanceledException.

Fixes #2257

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@qodo-free-for-open-source-projects
Copy link
Contributor

Review Summary by Qodo

Use descriptive ErrorMessage for timed out requests

🐞 Bug fix

Grey Divider

Walkthroughs

Description
• Fixes inconsistent ErrorMessage for timed out requests
• Sets ErrorMessage to "The request timed out." when timeout occurs
• Maintains consistency between ResponseStatus.TimedOut and error message
• Preserves original TaskCanceledException in ErrorException
Diagram
flowchart LR
  A["Request times out"] -->|OperationCanceledException| B["Check if TimedOut"]
  B -->|Yes| C["ResponseStatus.TimedOut"]
  B -->|Yes| D["ErrorMessage: 'The request timed out.'"]
  B -->|No| E["ResponseStatus.Aborted"]
  B -->|No| F["ErrorMessage: exception message"]
  C --> G["Consistent state"]
  D --> G
Loading

Grey Divider

File Changes

1. src/RestSharp/RestClient.Async.cs 🐞 Bug fix +4/-2

Set descriptive error message for timeout scenarios

• Extracts timeout check into timedOut variable to avoid duplicate evaluation
• Sets ErrorMessage to "The request timed out." when timeout occurs
• Uses timedOut flag for both ResponseStatus and ErrorMessage assignment
• Preserves original exception message for non-timeout cancellation scenarios

src/RestSharp/RestClient.Async.cs


Grey Divider

Qodo Logo

@qodo-free-for-open-source-projects
Copy link
Contributor

qodo-free-for-open-source-projects bot commented Feb 26, 2026

Code Review by Qodo

🐞 Bugs (2) 📘 Rule violations (1) 📎 Requirement gaps (0)

Grey Divider


Remediation recommended

1. timedOut boolean lacks prefix 📘 Rule violation ✓ Correctness
Description
The new boolean local timedOut does not use the recommended boolean naming prefix (e.g.,
isTimedOut). This reduces self-documentation consistency and readability for boolean state
variables.
Code

src/RestSharp/RestClient.Async.cs[64]

+        var timedOut = exception is OperationCanceledException && TimedOut();
Evidence
PR Compliance ID 2 requires boolean variables to use prefixes like is_/has_ for self-documenting
code; the PR introduces a boolean named timedOut without such a prefix.

Rule 2: Generic: Meaningful Naming and Self-Documenting Code
src/RestSharp/RestClient.Async.cs[64-70]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
A new boolean local variable is named `timedOut` without a boolean prefix, which conflicts with the naming guidance for self-documenting code.

## Issue Context
The code introduces a timeout flag used to set `ResponseStatus` and `ErrorMessage`. Renaming to `isTimedOut` (or similar) improves readability and aligns with the boolean naming convention.

## Fix Focus Areas
- src/RestSharp/RestClient.Async.cs[64-70]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


2. Inconsistent timeout messages 🐞 Bug ✧ Quality
Description
For the same timeout condition, RestResponse.ErrorMessage now differs from the exception message
thrown by ThrowIfError() ("The request timed out." vs "Request timed out"), which can confuse
consumers and complicate logging/error handling.
Code

src/RestSharp/RestClient.Async.cs[70]

+            ErrorMessage   = timedOut ? "The request timed out." : exception.GetBaseException().Message,
Evidence
The PR hard-codes a new timeout-specific ErrorMessage, while ThrowIfError() relies on
RestResponseBase.GetException() which constructs a TimeoutException with different text. This
creates two different user-facing messages for the same timeout scenario depending on which API
surface is used.

src/RestSharp/RestClient.Async.cs[63-77]
src/RestSharp/Response/RestResponseBase.cs[152-160]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
Timeouts now produce two different user-facing messages:
- `RestResponse.ErrorMessage`: &quot;The request timed out.&quot;
- `ThrowIfError()` thrown `TimeoutException.Message`: &quot;Request timed out&quot;
This inconsistency can confuse consumers who compare/log both.

### Issue Context
`ThrowIfError()` uses `RestResponseBase.GetException()` which currently hard-codes the `TimeoutException` message.

### Fix Focus Areas
- src/RestSharp/RestClient.Async.cs[63-77]
- src/RestSharp/Response/RestResponseBase.cs[152-160]

### Suggested approach
- Prefer a single shared message for timeouts.
 - Option A: Change `GetException()` to use `ErrorMessage` when available, e.g. `new TimeoutException(ErrorMessage ?? &quot;Request timed out&quot;, ErrorException)`.
 - Option B: Introduce a shared internal constant (e.g., `TimeoutErrorMessage`) and use it in both places.
- Consider also aligning punctuation/casing to avoid subtle diffs.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


3. Missing timeout ErrorMessage test 🐞 Bug ⛯ Reliability
Description
The new timeout-specific ErrorMessage behavior isn’t asserted by tests; existing timeout tests
validate ResponseStatus but not the ErrorMessage value, reducing confidence in the intended
contract.
Code

src/RestSharp/RestClient.Async.cs[70]

+            ErrorMessage   = timedOut ? "The request timed out." : exception.GetBaseException().Message,
Evidence
The PR introduces a new constant ErrorMessage for timeouts, but the existing timeout tests don’t
assert the message value (only ResponseStatus and ErrorException type). Adding assertions will lock
in the intended behavior.

src/RestSharp/RestClient.Async.cs[63-77]
test/RestSharp.Tests.Integrated/NonProtocolExceptionHandlingTests.cs[19-53]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
Timeout tests cover `ResponseStatus.TimedOut` but do not assert the newly introduced `ErrorMessage` value. This leaves the new behavior unprotected.

### Issue Context
Timeout message is now set to a constant string (&quot;The request timed out.&quot;) in `GetErrorResponse`.

### Fix Focus Areas
- test/RestSharp.Tests.Integrated/NonProtocolExceptionHandlingTests.cs[19-53]
- src/RestSharp/RestClient.Async.cs[63-77]

### Suggested approach
- In `Handles_HttpClient_Timeout_Error`, assert:
 - `response.ErrorMessage.Should().Be(&quot;The request timed out.&quot;);`
- In `Handles_Server_Timeout_Error` and `Handles_Server_Timeout_Error_With_Deserializer`, also assert the same.
- If message is intended to be stable API, keep exact-string assertion; otherwise consider asserting it is non-empty and contains &quot;timed out&quot;.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

ⓘ The new review experience is currently in Beta. Learn more

Grey Divider

Qodo Logo

@cloudflare-workers-and-pages
Copy link

Deploying restsharp with  Cloudflare Pages  Cloudflare Pages

Latest commit: 7fb5c19
Status: ✅  Deploy successful!
Preview URL: https://ce3b299c.restsharp.pages.dev
Branch Preview URL: https://fix-timeout-error-message.restsharp.pages.dev

View logs

@sonarqubecloud
Copy link

Quality Gate Failed Quality Gate failed

Failed conditions
B Maintainability Rating on New Code (required ≥ A)

See analysis details on SonarQube Cloud

Catch issues before they fail your Quality Gate with our IDE extension SonarQube for IDE

@alexeyzimarev alexeyzimarev merged commit 3582f73 into dev Feb 26, 2026
10 of 11 checks passed
@alexeyzimarev alexeyzimarev deleted the fix/timeout-error-message branch February 26, 2026 19:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Inconsistent ResponseStatus and ErrorMessage in case of timeout

1 participant