stride3d/stride · error · InvalidOperationException
Could not find underlying CPU buffer data and no command…
Error message
Could not find underlying CPU buffer data and no command list was given to extract them from GPU
What it means
GetDataSafe retrieves index buffer bytes, first from the CPU-side serialization data; if absent it needs a commandList to copy the data back from the GPU. When neither is available (no serialized CPU content and commandList is null) an InvalidOperationException is thrown because GPU readback is impossible without a command list.
Solutions
- Pass a valid CommandList (e.g. from the render context) so the GPU buffer can be read back
- Keep the buffer's serialization data (CPU content) available when the asset is loaded
- Re-load the asset with CPU-side data retained if the buffer was created GPU-only
Example fix
// before var data = indexBuffer.GetDataSafe(null); // after var data = indexBuffer.GetDataSafe(renderContext.CommandList);
Defensive patterns
Strategy: validation
Validate before calling
if (buffer.GetSerializationData() == null && commandList == null)
throw new InvalidOperationException("GetDataSafe needs a CommandList for GPU-only buffers");
var data = buffer.GetDataSafe(commandList); Type guard
bool canRead = buffer.GetSerializationData() != null || commandList != null;
Try / catch
try { var data = buffer.GetDataSafe(commandList); } catch (InvalidOperationException) { /* no CPU data and no command list */ } Prevention
- Always pass the current render context's CommandList when reading GPU buffers
- Keep serialization (CPU) data on assets that need runtime readback
- Perform buffer readbacks during rendering, not arbitrary game-thread code
When it happens
Trigger: Calling IndexExtensions.GetDataSafe on a GraphicsResource buffer whose GetSerializationData() returns null (never uploaded with CPU content retained) and passing null for commandList, e.g. on the game thread instead of a render context.
Common situations: Asset processing at runtime after CPU content was released, or calling from non-render code without acquiring CommandList from a graphics context.
Understand the failure class
Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.
Related errors
- SetObject can only be used for Permutation or Object keys
- GetObject can only be used for Permutation or Object keys
- Can only merge simple MeshDrawData.
- Cannot query package with dependencies when it is not…
- [ . ] must be in
AI-assisted analysis of stride3d/stride@96fad776d2 (2026-09-14).
Data as JSON: /api/errors/47680315bde9e711.
Report an issue: GitHub.
Appendix: source
Thrown at sources/engine/Stride.Rendering/Extensions/IndexExtensions.cs:23
using System.Linq;
using Stride.Core;
using Stride.Graphics;
using Stride.Graphics.Data;
using Stride.Rendering;
using Buffer = Stride.Graphics.Buffer;
namespace Stride.Extensions
{
public static class IndexExtensions
{
private static byte[] GetDataSafe(this Buffer buffer, CommandList commandList = null)
{
var data = buffer.GetSerializationData();
if (data != null)
return data.Content;
if (commandList == null)
throw new InvalidOperationException("Could not find underlying CPU buffer data and no command list was given to extract them from GPU");
return buffer.GetData<byte>(commandList);
}
/// <summary>
/// Expand vertices using index buffer (if existing), and remove it.
/// </summary>
/// <param name="meshData">The mesh data.</param>
public static unsafe void RemoveIndexBuffer(this MeshDraw meshData)
{
if (meshData.IndexBuffer == null)
return;
// For now, require a MeshData with only one vertex buffer and a 32 bit full index buffer
if (meshData.VertexBuffers.Length != 1 || !meshData.IndexBuffer.Is32Bit
|| meshData.StartLocation != 0 || meshData.DrawCount != meshData.IndexBuffer.Count)
throw new NotImplementedException();
View on GitHub (pinned to 96fad776d2)