Skip to content

Use descriptive ErrorMessage for timed out requests#2355

Closed
alexeyzimarev wants to merge 2 commits intodevfrom
fix/timeout-error-message
Closed

Use descriptive ErrorMessage for timed out requests#2355
alexeyzimarev wants to merge 2 commits 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

alexeyzimarev and others added 2 commits February 26, 2026 18:18
… values to strings

Previously, AddParameter<T>, AddQueryParameter<T>, AddUrlSegment<T>,
AddHeader<T>, AddOrUpdateParameter<T>, AddOrUpdateHeader<T>, and
Parameter.CreateParameter all used ToString() which respects the current
culture. This caused issues on non-English locales where e.g. 1.234 would
be formatted as "1,234" with a comma decimal separator.

All generic overloads now default to InvariantCulture and accept an optional
CultureInfo parameter for callers who need locale-specific formatting.

Fixes #2270

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
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

Fix timeout error message and parameter culture handling

🐞 Bug fix ✨ Enhancement

Grey Divider

Walkthroughs

Description
• Use invariant culture for parameter value conversions to fix locale-specific formatting issues
• Add optional culture parameter to generic parameter methods for locale-specific formatting when
  needed
• Use descriptive error message "The request timed out." for timeout scenarios instead of "A task
  was canceled."
• Ensure consistency between ResponseStatus.TimedOut, ErrorMessage, and ErrorException for timeout
  cases
Diagram
flowchart LR
  A["Parameter Conversion"] -->|"Use InvariantCulture by default"| B["Consistent Formatting"]
  C["Timeout Exception"] -->|"Detect OperationCanceledException"| D["Set ErrorMessage to timeout message"]
  D -->|"Keep ErrorException unchanged"| E["Consistent State Properties"]
  B --> F["Enhanced RestSharp"]
  E --> F
Loading

Grey Divider

File Changes

1. src/RestSharp/Extensions/StringExtensions.cs ✨ Enhancement +3/-0

Add ToStringValue extension for culture-aware formatting

src/RestSharp/Extensions/StringExtensions.cs


2. src/RestSharp/Parameters/ObjectParser.cs ✨ Enhancement +4/-1

Use invariant culture in ParseValue method

src/RestSharp/Parameters/ObjectParser.cs


3. src/RestSharp/Parameters/Parameter.cs ✨ Enhancement +5/-4

Use ToStringValue for invariant culture conversion

src/RestSharp/Parameters/Parameter.cs


View more (7)
4. src/RestSharp/Request/RestRequestExtensions.Headers.cs ✨ Enhancement +11/-4

Add culture parameter to generic AddHeader methods

src/RestSharp/Request/RestRequestExtensions.Headers.cs


5. src/RestSharp/Request/RestRequestExtensions.Query.cs ✨ Enhancement +7/-2

Add culture parameter to AddQueryParameter generic method

src/RestSharp/Request/RestRequestExtensions.Query.cs


6. src/RestSharp/Request/RestRequestExtensions.Url.cs ✨ Enhancement +7/-2

Add culture parameter to AddUrlSegment generic method

src/RestSharp/Request/RestRequestExtensions.Url.cs


7. src/RestSharp/Request/RestRequestExtensions.cs ✨ Enhancement +12/-6

Add culture parameter to generic parameter methods

src/RestSharp/Request/RestRequestExtensions.cs


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

Set descriptive error message for timeout scenarios

src/RestSharp/RestClient.Async.cs


9. test/RestSharp.Tests/InvariantCultureTests.cs 🧪 Tests +98/-0

Add tests for invariant culture parameter conversion

test/RestSharp.Tests/InvariantCultureTests.cs


10. test/RestSharp.Tests/ObjectParserTests.cs 🧪 Tests +6/-5

Update tests to use invariant culture in assertions

test/RestSharp.Tests/ObjectParserTests.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


Action required

1. Binary-breaking API signature change 🐞 Bug ⛯ Reliability
Description
Several public generic RestRequest extension methods were changed to add a CultureInfo parameter
instead of adding new overloads. This breaks binary compatibility: consumers compiled against prior
versions can hit MissingMethodException at runtime when loading the updated assembly.
Code

src/RestSharp/Request/RestRequestExtensions.cs[R58-59]

+        public RestRequest AddParameter<T>(string name, T value, bool encode = true, CultureInfo? culture = null) where T : struct
+            => request.AddParameter(name, value.ToStringValue(culture), encode);
Evidence
These are public APIs (annotated [PublicAPI]) and the generic overloads now only exist with a
different signature (extra CultureInfo? parameter). There are corresponding signature changes in
Headers/Query/Url partials as well, and there are no remaining overloads matching the previous
signatures.

src/RestSharp/Request/RestRequestExtensions.cs[20-21]
src/RestSharp/Request/RestRequestExtensions.cs[58-60]
src/RestSharp/Request/RestRequestExtensions.Headers.cs[54-56]
src/RestSharp/Request/RestRequestExtensions.Query.cs[44-46]
src/RestSharp/Request/RestRequestExtensions.Url.cs[44-46]

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

## Issue description
Public generic extension methods changed signatures by adding a new `CultureInfo? culture` parameter. This is source-compatible but **not binary-compatible**: existing compiled clients expecting the old signatures may fail at runtime with `MissingMethodException`.

## Issue Context
These methods are public API surface. Optional parameters do not preserve binary compatibility when the parameter is newly added (signature changes).

## Fix Focus Areas
- src/RestSharp/Request/RestRequestExtensions.cs[58-81]
- src/RestSharp/Request/RestRequestExtensions.Headers.cs[54-77]
- src/RestSharp/Request/RestRequestExtensions.Query.cs[44-45]
- src/RestSharp/Request/RestRequestExtensions.Url.cs[44-45]

## Suggested implementation sketch
- Add back overloads with the old signatures, e.g.:
 - `AddParameter&lt;T&gt;(string name, T value, bool encode = true)` calls `AddParameter(name, value, encode, culture: null)`.
 - Keep the new overload with `CultureInfo? culture = null`.
- Repeat for other affected generic methods.
- (Optional) Mark the old overloads `[Obsolete]` if you want to guide users toward the new culture-aware overloads, but keep them for binary compatibility.

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



Remediation recommended

2. Single-letter f variable 📘 Rule violation ✓ Correctness
Description
ToStringValue introduces a single-letter identifier f, which reduces self-documentation and can
hurt readability. This conflicts with the naming requirement to avoid single-letter variables
outside common iterator conventions.
Code

src/RestSharp/Extensions/StringExtensions.cs[R152-153]

+    internal static string? ToStringValue(this object? value, CultureInfo? culture = null)
+        => value is IFormattable f ? f.ToString(null, culture ?? CultureInfo.InvariantCulture) : value?.ToString();
Evidence
Compliance ID 2 requires meaningful, self-documenting identifiers and prohibits single-letter
variable names outside conventional short-lived iterators; the new ToStringValue method uses f
as a pattern variable.

Rule 2: Generic: Meaningful Naming and Self-Documenting Code
src/RestSharp/Extensions/StringExtensions.cs[152-153]

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

## Issue description
`ToStringValue` uses a single-letter identifier (`f`) which is not self-documenting.

## Issue Context
The project compliance checklist requires meaningful naming and discourages single-letter variables outside conventional iterator usage.

## Fix Focus Areas
- src/RestSharp/Extensions/StringExtensions.cs[152-153]

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


3. Default formatting now invariant 🐞 Bug ✓ Correctness
Description
Parameter/header/object-property value stringification now defaults to CultureInfo.InvariantCulture
for IFormattable values. This is an intentional improvement for API consistency, but it is still a
behavioral breaking change (e.g., DateTime/decimal formatting) and some paths (e.g.,
Parameter.CreateParameter/object overloads) have no culture escape hatch.
Code

src/RestSharp/Extensions/StringExtensions.cs[R152-153]

+    internal static string? ToStringValue(this object? value, CultureInfo? culture = null)
+        => value is IFormattable f ? f.ToString(null, culture ?? CultureInfo.InvariantCulture) : value?.ToString();
Evidence
The new ToStringValue helper explicitly defaults to InvariantCulture for IFormattable. It is now
used by core APIs like Parameter.CreateParameter and ObjectParser, which changes output compared to
prior culture-dependent ToString()/string.Format behavior. Tests were added/updated to assert
invariant formatting even when CurrentCulture is different, demonstrating this is a deliberate
behavior change that should be communicated and/or made configurable consistently.

src/RestSharp/Extensions/StringExtensions.cs[152-154]
src/RestSharp/Parameters/Parameter.cs[77-85]
src/RestSharp/Parameters/ObjectParser.cs[78-79]
test/RestSharp.Tests/InvariantCultureTests.cs[7-16]

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

## Issue description
Default serialization of IFormattable values (numbers/dates) now uses `InvariantCulture` via `ToStringValue`. This is likely a correctness improvement for wire formats, but it can break existing behavior for users relying on `CurrentCulture` formatting—especially for `Parameter.CreateParameter(...)` and object-based parameter APIs where callers cannot provide a culture.

## Issue Context
- New tests assert invariant formatting even when `CultureInfo.CurrentCulture` differs.
- Some public entry points do not offer a way to specify culture.

## Fix Focus Areas
- src/RestSharp/Extensions/StringExtensions.cs[152-154]
- src/RestSharp/Parameters/Parameter.cs[77-85]
- src/RestSharp/Parameters/ObjectParser.cs[44-79]
- src/RestSharp/Request/RestRequestExtensions.cs[44-60]

## Options to address
- Documentation/release notes: clearly call out the new default formatting semantics.
- API consistency: add *new* overloads (don’t change existing signatures) that accept `CultureInfo? culture` for the object-based APIs and route through it.
- Alternative: if backward compatibility is preferred, change the default from `InvariantCulture` to `CurrentCulture` and require explicitly passing `CultureInfo.InvariantCulture` (this would require adjusting the new tests).

ⓘ 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

@sonarqubecloud
Copy link

@cloudflare-workers-and-pages
Copy link

Deploying restsharp with  Cloudflare Pages  Cloudflare Pages

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

View logs

Comment on lines +58 to +59
public RestRequest AddParameter<T>(string name, T value, bool encode = true, CultureInfo? culture = null) where T : struct
=> request.AddParameter(name, value.ToStringValue(culture), encode);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

1. Binary-breaking api signature change 🐞 Bug ⛯ Reliability

Several public generic RestRequest extension methods were changed to add a CultureInfo parameter
instead of adding new overloads. This breaks binary compatibility: consumers compiled against prior
versions can hit MissingMethodException at runtime when loading the updated assembly.
Agent Prompt
## Issue description
Public generic extension methods changed signatures by adding a new `CultureInfo? culture` parameter. This is source-compatible but **not binary-compatible**: existing compiled clients expecting the old signatures may fail at runtime with `MissingMethodException`.

## Issue Context
These methods are public API surface. Optional parameters do not preserve binary compatibility when the parameter is newly added (signature changes).

## Fix Focus Areas
- src/RestSharp/Request/RestRequestExtensions.cs[58-81]
- src/RestSharp/Request/RestRequestExtensions.Headers.cs[54-77]
- src/RestSharp/Request/RestRequestExtensions.Query.cs[44-45]
- src/RestSharp/Request/RestRequestExtensions.Url.cs[44-45]

## Suggested implementation sketch
- Add back overloads with the old signatures, e.g.:
  - `AddParameter<T>(string name, T value, bool encode = true)` calls `AddParameter(name, value, encode, culture: null)`.
  - Keep the new overload with `CultureInfo? culture = null`.
- Repeat for other affected generic methods.
- (Optional) Mark the old overloads `[Obsolete]` if you want to guide users toward the new culture-aware overloads, but keep them for binary compatibility.

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

@github-actions
Copy link

Test Results

   42 files     42 suites   17m 53s ⏱️
  514 tests   514 ✅ 0 💤 0 ❌
3 593 runs  3 593 ✅ 0 💤 0 ❌

Results for commit bf41159.

@alexeyzimarev
Copy link
Member Author

Recreating from a clean branch based on dev.

@alexeyzimarev alexeyzimarev deleted the fix/timeout-error-message branch February 26, 2026 19:26
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