EllanJiang/GameFramework · error · GameFrameworkException
Start index is invalid.
Error message
Start index is invalid.
What it means
Utility.Marshal.StructureToBytes validates the startIndex parameter before copying a struct's bytes into the caller-supplied result buffer. A negative startIndex can never address a valid location in the byte array, so the library throws GameFrameworkException immediately. This is a cheap upfront guard against invalid offsets in the unmanaged-memory marshaling path.
Solutions
- Inspect the startIndex argument passed to StructureToBytes and ensure it is >= 0 before calling.
- Fix the offset computation that produced the negative value (check subtraction order and initialization).
- Add a caller-side assertion/parameter validation to reject negative offsets at the API boundary.
Example fix
// before int offset = bufferPosition - blockLength; // can be negative Utility.Marshal.StructureToBytes(header, headerSize, dest, offset); // after int offset = bufferPosition - blockLength; if (offset < 0) throw new ArgumentOutOfRangeException(nameof(offset)); Utility.Marshal.StructureToBytes(header, headerSize, dest, offset);
Defensive patterns
Strategy: validation
Validate before calling
if (startIndex < 0)
throw new ArgumentOutOfRangeException(nameof(startIndex));
Utility.Marshal.StructureToBytes(structure, structureSize, result, startIndex); Try / catch
try
{
Utility.Marshal.StructureToBytes(structure, size, dest, offset);
}
catch (GameFrameworkException ex) when (ex.Message == "Start index is invalid.")
{
// log offset computation bug and correct the cursor
} Prevention
- Track buffer offsets in a single cursor variable that is only ever advanced by positive amounts.
- Assert offsets are non-negative in debug builds with Debug.Assert(offset >= 0).
- Avoid -1 sentinels for offsets; use nullable int instead.
When it happens
Trigger: Calling Utility.Marshal.StructureToBytes(structure, structureSize, result, startIndex) with a negative startIndex value, e.g. an offset computed from an arithmetic underflow or an uninitialized cursor variable.
Common situations: Computing a write offset by subtracting lengths that can go negative; deserializing chunked data where a packet offset variable was not initialized; passing -1 as a sentinel offset by mistake.
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 is invalid.
- Length is invalid.
- Delta length is invalid.
- Update interval is invalid.
- Record interval is invalid.
AI-assisted analysis of EllanJiang/GameFramework@d0c010b051 (2026-09-15).
Data as JSON: /api/errors/f9deb2e9a696c8a8.
Report an issue: GitHub.
Appendix: source
Thrown at GameFramework/Utility/Utility.Marshal.cs:156
/// <param name="structure">要转换的对象。</param>
/// <param name="structureSize">要转换的对象的大小。</param>
/// <param name="result">存储转换结果的二进制流。</param>
/// <param name="startIndex">写入存储转换结果的二进制流的起始位置。</param>
internal static void StructureToBytes<T>(T structure, int structureSize, byte[] result, int startIndex)
{
if (structureSize < 0)
{
throw new GameFrameworkException("Structure size is invalid.");
}
if (result == null)
{
throw new GameFrameworkException("Result is invalid.");
}
if (startIndex < 0)
{
throw new GameFrameworkException("Start index is invalid.");
}
if (startIndex + structureSize > result.Length)
{
throw new GameFrameworkException("Result length is not enough.");
}
EnsureCachedHGlobalSize(structureSize);
System.Runtime.InteropServices.Marshal.StructureToPtr(structure, s_CachedHGlobalPtr, true);
System.Runtime.InteropServices.Marshal.Copy(s_CachedHGlobalPtr, result, startIndex, structureSize);
}
/// <summary>
/// 将数据从二进制流转换为对象。
/// </summary>
/// <typeparam name="T">要转换的对象的类型。</typeparam>
/// <param name="buffer">要转换的二进制流。</param>
/// <returns>存储转换结果的对象。</returns>View on GitHub (pinned to d0c010b051)