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
- Ensure the CodedOutputStream was constructed from a byte[] (new CodedOutputStream(byte[])) before calling SpaceLeft
- Refactor to not need SpaceLeft: write directly and let the stream buffer/flush itself
- Use WriteContext/WriteRawMessage APIs that handle length prefixing instead of manual capacity checks
- 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
- Track how each CodedOutputStream was constructed (byte[] vs Stream)
- Avoid manual capacity math; use high-level write APIs
- Wrap stream-backed writers with your own byte counter if capacity checks are needed
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
- Offset must be within the buffer
- Length must be non-negative and within the buffer
- SkipLastField cannot be called at the end of a stream
- Stream.Read returned a negative count
- Key already exists in map
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)