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

  1. 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.
  2. Fix the upstream computation that produced the non-positive total size.
  3. Avoid the internal constructor; use public overloads (byte[] or Stream based) which derive limits correctly.
  4. 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

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


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)