XINCGer/Unity3DTraining · error · ArgumentOutOfRangeException
Size limit must be positive
Error message
Size limit must be positive
What it means
The internal constructor that takes an explicit sizeLimit validates that sizeLimit > 0. sizeLimit bounds the total number of bytes the logical stream may contain; a non-positive value would make progress checks meaningless. This constructor is internal, so it is hit via library-internal paths or reflection, not typical public API calls.
Solutions
- Ensure sizeLimit is at least 1 — if the payload may be empty, special-case the empty input instead of constructing a reader with limit 0.
- Fix the upstream computation that produced the non-positive total size.
- Avoid the internal constructor; use public overloads (byte[] or Stream based) which derive limits correctly.
- If using reflection, validate parameters against the constructor's invariants first.
Example fix
// before
var stream = MakeReader(input, buf, pos, size, totalSize, 64); // totalSize could be 0
// after
if (totalSize <= 0) throw new InvalidDataException("Empty or invalid message size");
var stream = MakeReader(input, buf, pos, size, totalSize, 64); Defensive patterns
Strategy: validation
Validate before calling
if (sizeLimit <= 0) throw new InvalidDataException($"sizeLimit must be positive, got {sizeLimit}"); Type guard
bool IsValidSizeLimit(int sizeLimit) => sizeLimit > 0;
Try / catch
try { CreateReader(input, buf, pos, size, sizeLimit, 64); } catch (ArgumentOutOfRangeException ex) { logger.LogError(ex, "Invalid size limit {V}", sizeLimit); } Prevention
- Special-case empty payloads before building a reader.
- Initialize all limit fields in config objects with sane defaults (e.g. 64MB).
- Avoid internal constructors; use public overloads.
When it happens
Trigger: Constructing CodedInputStream via the internal (Stream, byte[], int, int, int sizeLimit, int recursionLimit) overload with sizeLimit <= 0 — e.g. passing a length of 0 for an empty payload or an uninitialized/default int.
Common situations: Custom framing code using reflection or InternalsVisibleTo to build segmented readers; passing a computed total message size that came out 0 or negative due to bad arithmetic upstream.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- Offset must be within the buffer
- Length must be non-negative and within the buffer
- Recursion limit must be positive
- SkipLastField cannot be called at the end of a stream
- SkipLastField called on an end-group tag, indicating that…
AI-assisted analysis of XINCGer/Unity3DTraining@016f98412e (2026-09-12).
Data as JSON: /api/errors/5dee6b92eb6b81bb.
Report an issue: GitHub.
Appendix: source
Thrown at NetWorkAndResources/Socket_Protobuff/Assets/Plugins/Google.Protobuf/CodedInputStream.cs:193
this.bufferSize = bufferSize;
this.sizeLimit = DefaultSizeLimit;
this.recursionLimit = DefaultRecursionLimit;
}
/// <summary>
/// Creates a new CodedInputStream reading data from the given
/// stream and buffer, using the specified limits.
/// </summary>
/// <remarks>
/// This chains to the version with the default limits instead of vice versa to avoid
/// having to check that the default values are valid every time.
/// </remarks>
internal CodedInputStream(Stream input, byte[] buffer, int bufferPos, int bufferSize, int sizeLimit, int recursionLimit)
: this(input, buffer, bufferPos, bufferSize)
{
if (sizeLimit <= 0)
{
throw new ArgumentOutOfRangeException("sizeLimit", "Size limit must be positive");
}
if (recursionLimit <= 0)
{
throw new ArgumentOutOfRangeException("recursionLimit!", "Recursion limit must be positive");
}
this.sizeLimit = sizeLimit;
this.recursionLimit = recursionLimit;
}
#endregion
/// <summary>
/// Creates a <see cref="CodedInputStream"/> with the specified size and recursion limits, reading
/// from an input stream.
/// </summary>
/// <remarks>
/// This method exists separately from the constructor to reduce the number of constructor overloads.
/// It is likely to be used considerably less frequently than the constructors, as the default limits
/// are suitable for most use cases.View on GitHub (pinned to 016f98412e)