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
- Ensure the byte[] passed to BytesToStructure is non-null; check the result of whatever produced it before calling.
- Make the upstream read routine throw or return an empty array instead of null.
- 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
- Make read helpers throw on failure instead of returning null arrays.
- Null-check every byte[] produced by network/file reads before parsing.
- Enable nullable reference type annotations (#nullable enable) so null flows are flagged at compile time.
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
- Entity asset name is invalid.
- Start index is invalid.
- Result length is not enough.
- Buffer length is not enough.
- Format is invalid.
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)