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

  1. Inspect the startIndex argument passed to StructureToBytes and ensure it is >= 0 before calling.
  2. Fix the offset computation that produced the negative value (check subtraction order and initialization).
  3. 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

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


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)