EllanJiang/GameFramework · error · GameFrameworkException

Buffer is invalid.

Error message

Buffer is invalid.

What it means

BytesToStructure requires a non-null byte[] buffer to read the struct bytes from. A null buffer would crash inside the unmanaged copy (Marshal.Copy), so the library throws GameFrameworkException early with this message. It is a defensive null check at the marshaling boundary.

Solutions

  1. Ensure the byte[] passed to BytesToStructure is non-null; check the result of whatever produced it before calling.
  2. Make the upstream read routine throw or return an empty array instead of null.
  3. Add a null check with a clear log message at the deserialization entry point.

Example fix

// before
byte[] data = ReadChunk(id); // may return null
var header = Utility.Marshal.BytesToStructure<Header>(size, data, 0);
// after
byte[] data = ReadChunk(id);
if (data == null) throw new IOException($"Chunk {id} not found");
var header = Utility.Marshal.BytesToStructure<Header>(size, data, 0);
Defensive patterns

Strategy: type-guard

Validate before calling

if (buffer == null)
    throw new ArgumentNullException(nameof(buffer));
var value = Utility.Marshal.BytesToStructure<T>(structureSize, buffer, startIndex);

Type guard

bool IsValidBuffer(byte[] buffer) => buffer != null;

Try / catch

try
{
    var v = Utility.Marshal.BytesToStructure<T>(size, buffer, offset);
}
catch (GameFrameworkException ex) when (ex.Message == "Buffer is invalid.")
{
    // buffer was null: re-read the chunk or surface a read failure
}

Prevention

When it happens

Trigger: Calling Utility.Marshal.BytesToStructure<T>(structureSize, null, startIndex) — e.g. a read function returned null because a stream read failed or a cache lookup missed.

Common situations: Network/file read helpers that return null on failure instead of throwing; deserialization pipelines where an earlier decode step silently produced null; unit data loaded from a partially failed resource table.

Related errors


AI-assisted analysis of EllanJiang/GameFramework@d0c010b051 (2026-09-15). Data as JSON: /api/errors/00346db67c1b1c3d. Report an issue: GitHub.

Appendix: source

Thrown at GameFramework/Utility/Utility.Marshal.cs:221

            /// <summary>
            /// 将数据从二进制流转换为对象。
            /// </summary>
            /// <typeparam name="T">要转换的对象的类型。</typeparam>
            /// <param name="structureSize">要转换的对象的大小。</param>
            /// <param name="buffer">要转换的二进制流。</param>
            /// <param name="startIndex">读取要转换的二进制流的起始位置。</param>
            /// <returns>存储转换结果的对象。</returns>
            internal static T BytesToStructure<T>(int structureSize, byte[] buffer, int startIndex)
            {
                if (structureSize < 0)
                {
                    throw new GameFrameworkException("Structure size is invalid.");
                }

                if (buffer == null)
                {
                    throw new GameFrameworkException("Buffer is invalid.");
                }

                if (startIndex < 0)
                {
                    throw new GameFrameworkException("Start index is invalid.");
                }

                if (startIndex + structureSize > buffer.Length)
                {
                    throw new GameFrameworkException("Buffer length is not enough.");
                }

                EnsureCachedHGlobalSize(structureSize);
                System.Runtime.InteropServices.Marshal.Copy(buffer, startIndex, s_CachedHGlobalPtr, structureSize);
                return (T)System.Runtime.InteropServices.Marshal.PtrToStructure(s_CachedHGlobalPtr, typeof(T));
            }
        }
    }

View on GitHub (pinned to d0c010b051)