XINCGer/Unity3DTraining · error · InvalidOperationException

SpaceLeft can only be called on CodedOutputStreams that are…

Error message

SpaceLeft can only be called on CodedOutputStreams that are writing to a flat array.

What it means

CodedOutputStream.SpaceLeft() reports remaining writable bytes only when the stream wraps a flat byte array. If the stream wraps another Stream (output != null), there is no bounded buffer to measure, so the library throws InvalidOperationException rather than return a meaningless value.

Solutions

  1. Ensure the CodedOutputStream was constructed from a byte[] (new CodedOutputStream(byte[])) before calling SpaceLeft
  2. Refactor to not need SpaceLeft: write directly and let the stream buffer/flush itself
  3. Use WriteContext/WriteRawMessage APIs that handle length prefixing instead of manual capacity checks
  4. If using a Stream, wrap it and track written bytes yourself (position vs known limit)

Example fix

// before
var cos = new CodedOutputStream(networkStream);
if (cos.SpaceLeft() < 4) Flush();
// after
var buffer = new byte[1024];
var cos = new CodedOutputStream(buffer);
if (cos.SpaceLeft() < 4) { /* must not happen: array is fixed; flush to stream instead */ }
Defensive patterns

Strategy: validation

Validate before calling

if (cos.WriteContext == null || arrayBacked) { use SpaceLeft } else { skip check }

Type guard

bool IsArrayBacked(CodedOutputStream cos) => cos != null && !cos.UsesStream; // construct-only knowledge; track backing yourself

Try / catch

try { space = cos.SpaceLeft(); } catch (InvalidOperationException) { space = -1; /* stream-backed */ }

Prevention

When it happens

Trigger: Calling SpaceLeft() on a CodedOutputStream constructed with a Stream (e.g. new CodedOutputStream(someStream)), or one created via CodedOutputStream.CreateStream. Only the byte[]-backed constructor supports it.

Common situations: Hand-rolled serialization code that checks remaining capacity before writing; code shared between array-backed and stream-backed output paths; copying examples that assume byte[] backing.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


AI-assisted analysis of XINCGer/Unity3DTraining@016f98412e (2026-09-12). Data as JSON: /api/errors/49704776664ca2f6. Report an issue: GitHub.

Appendix: source

Thrown at NetWorkAndResources/Socket_Protobuff/Assets/Plugins/Google.Protobuf/CodedOutputStream.cs:754

                throw new InvalidOperationException("Did not write as much data as expected.");
            }
        }

        /// <summary>
        /// If writing to a flat array, returns the space left in the array. Otherwise,
        /// throws an InvalidOperationException.
        /// </summary>
        public int SpaceLeft
        {
            get
            {
                if (output == null)
                {
                    return limit - position;
                }
                else
                {
                    throw new InvalidOperationException(
                        "SpaceLeft can only be called on CodedOutputStreams that are " +
                        "writing to a flat array.");
                }
            }
        }
    }
}

View on GitHub (pinned to 016f98412e)