Skip to content

StringBuilder.ToString() throws misleading ArgumentOutOfRangeException for internal chunk inconsistency #131674

Description

@jinek

Title

StringBuilder.ToString() throws misleading ArgumentOutOfRangeException for internal chunk inconsistency

Description

StringBuilder.ToString() validates internal chunk boundaries before copying:

if ((uint)(chunkLength + chunkOffset) > (uint)result.Length ||
    (uint)chunkLength > (uint)sourceArray.Length)
{
    throw new ArgumentOutOfRangeException(
        nameof(chunkLength),
        SR.ArgumentOutOfRange_IndexMustBeLessOrEqual);
}

This exception is misleading:

  • ToString() has no parameters.
  • chunkLength is a private local copied from internal StringBuilder state.
  • The caller cannot provide or correct a parameter named chunkLength.
  • The failed condition indicates an inconsistent internal snapshot, normally caused by concurrent mutation.

A real occurrence was reported in #46022. Concurrent use is caller misuse because StringBuilder is not thread-safe, but reporting it as an invalid argument obscures the real cause.

Expected behavior

Throw an exception representing an invalid or inconsistent operation rather than ArgumentOutOfRangeException with a fictitious parameter name.

This could be an InvalidOperationException, or a suitable internal consistency/concurrency exception translated into an appropriate public exception.

The exact exception type may require compatibility discussion. However, this path should not claim that the caller supplied an invalid chunkLength argument.

Actual behavior

System.ArgumentOutOfRangeException:
Index was out of range. Must be non-negative and less than the size of the collection.
(Parameter 'chunkLength')
   at System.Text.StringBuilder.ToString()

This presents an internal implementation variable as a public method parameter.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions