JamesNK/Newtonsoft.Json · error · ArgumentOutOfRangeException
length
Error message
length
What it means
Defensive guard inside the internal helper StringUtils.Trim(string s, int start, int length) (Src/Newtonsoft.Json/Utilities/StringUtils.cs:334). It throws ArgumentOutOfRangeException with parameter name "length" whenever length is negative (StringUtils.cs:346-348), because a negative window size for trimming the substring [start, start+length) is meaningless. The only in-library caller, ReflectionUtils.SplitFullyQualifiedTypeName (ReflectionUtils.cs:867-868), derives length from a validated comma-delimiter index and can never produce a negative value, so this guard is effectively unreachable from any public Newtonsoft.Json deserialization/serialization path.
Source
Thrown at Src/Newtonsoft.Json/Utilities/StringUtils.cs:348
{
return (source.Length > 0 && source[source.Length - 1] == value);
}
public static string Trim(this string s, int start, int length)
{
// References: https://referencesource.microsoft.com/#mscorlib/system/string.cs,2691
// https://referencesource.microsoft.com/#mscorlib/system/string.cs,1226
if (s == null)
{
throw new ArgumentNullException();
}
if (start < 0)
{
throw new ArgumentOutOfRangeException(nameof(start));
}
if (length < 0)
{
throw new ArgumentOutOfRangeException(nameof(length));
}
int end = start + length - 1;
if (end >= s.Length)
{
throw new ArgumentOutOfRangeException(nameof(length));
}
for (; start < end; start++)
{
if (!char.IsWhiteSpace(s[start]))
{
break;
}
}
for (; end >= start; end--)
{
if (!char.IsWhiteSpace(s[end]))
{
break;View on GitHub (pinned to 4f73e74372)
Solutions
- Guard or clamp length before calling: use int safeLength = Math.Max(0, length); so a negative computed value collapses to an empty window.
- Recompute length defensively from boundaries (end - start) instead of passing a derived value that can underflow.
- Prefer System.String.Trim() / Substring(start, len) for application code and reserve this internal overload for library internals.
Example fix
// before string t = s.Trim(start, end - start); // underflows when end < start // after string t = (end >= start) ? s.Trim(start, end - start) : s;
Defensive patterns
Strategy: validation
Validate before calling
int safeLength = Math.Max(0, length); if (start < 0) start = 0; string result = s.Trim(start, safeLength);
Prevention
- Validate the window bounds (start>=0, length>=0, start+length<=s.Length) before invoking this internal Trim overload.
- Derive length from a checked delimiter index the way ReflectionUtils.SplitFullyQualifiedTypeName does, rather than computing it ad hoc.
- Treat StringUtils.Trim(int,int) as an internal utility; use System.String.Trim()/Substring for application code.
When it happens
Trigger: Directly invoking the StringUtils.Trim(string, int, int) extension overload with a negative length argument (e.g. s.Trim(0, -1)). It is NOT reachable through the public API: SplitFullyQualifiedTypeName computes length as either assemblyDelimiterIndex (>=0) or fullyQualifiedTypeName.Length - assemblyDelimiterIndex - 1 (>=0 since the delimiter index is always <= Length-1 from GetAssemblyDelimiterIndex), so the guard only fires for code that calls this utility directly or in a fork.
Common situations: Contributors/fork maintainers calling the windowed Trim overload with hand-computed indices; unit tests exercising StringUtils directly; custom type-name splitters that reuse this helper with off-by-one arithmetic that underflows below zero.
Related errors
- Unexpected merge array handling when merging JSON.
- arrayIndex is less than 0.
- arrayIndex is equal to or greater than the length of array.
- The number of elements in the source JObject is greater than
- value
AI-assisted analysis of JamesNK/Newtonsoft.Json@4f73e74372 (2026-08-07).
Data as JSON: /api/errors/552c160f8cdabbb5.
Report an issue: GitHub.