stride3d/stride · critical · Exception
: Could not parse spirv
Error message
{cross.ContextParseSpirv(context, w, (nuint)Words.Length, &ir)} : Could not parse spirv What it means
After the context is created, GetEntryPoints parses the stored SPIR-V words via cross.ContextParseSpirv. If the parse fails (invalid magic number, truncated module, unsupported SPIR-V version), the translator throws with the raw Result code and "Could not parse spirv". This means the bytecode buffer handed to SpirvTranslator is not a valid SPIR-V module.
Solutions
- Validate the buffer starts with the SPIR-V magic number 0x07230203 and is properly word-aligned before constructing the translator.
- Confirm the buffer actually contains SPIR-V (not DXBC/DXIL/other) and was produced by a compatible SPIR-V frontend version.
- Re-export/recompile the shader to regenerate a complete, untruncated SPIR-V module; clear possibly corrupt caches.
- Check the numeric Result code in the message against SPIRV-Cross parse error codes for the specific cause.
Example fix
// before
var translator = new SpirvTranslator(dxbcBytes); // wrong format
var entries = translator.GetEntryPoints(); // 'Could not parse spirv'
// after
if (BitConverter.ToUInt32(spirvBytes, 0) != 0x07230203u)
throw new InvalidDataException("Not SPIR-V");
var translator = new SpirvTranslator(spirvBytes);
var entries = translator.GetEntryPoints(); Defensive patterns
Strategy: validation
Validate before calling
static bool LooksLikeSpirv(ReadOnlySpan<uint> words) =>
words.Length >= 5 && words[0] == 0x07230203u; // magic number Type guard
if (!LooksLikeSpirv(words))
throw new InvalidDataException("Buffer is not a SPIR-V module (bad magic number)"); Try / catch
try { var eps = translator.GetEntryPoints(); }
catch (Exception ex) when (ex.Message.Contains("Could not parse spirv")) {
InvalidateShaderCache(blobId); // discard corrupt/unsupported module
} Prevention
- Check the SPIR-V magic number 0x07230203 before constructing the translator.
- Never feed DXBC/DXIL/HLSL bytecode into the SPIR-V translator.
- Version-stamp shader caches so blobs from incompatible compiler versions are regenerated.
When it happens
Trigger: Calling GetEntryPoints on a SpirvTranslator whose Words.Span does not contain valid SPIR-V: buffer written in wrong endianness/offset, HLSL/DXBC or DXIL bytes passed instead of SPIR-V, truncated buffer, or SPIR-V version newer than the bundled parser.
Common situations: Feeding translated-then-saved shader blobs from an incompatible backend; cache corruption; passing a shader bytecode buffer produced for a different API (e.g. DXBC) into the SPIR-V translator.
Understand the failure class
Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.
Related errors
- spirv_to_dxil_pipeline failed; SPIR-V dumped to
- : Could not create spirv context
- Could not locate native executable
- Could not locate native library
- Failed to initialize FreeType library
AI-assisted analysis of stride3d/stride@96fad776d2 (2026-09-14).
Data as JSON: /api/errors/b2bd1a249ac9c652.
Report an issue: GitHub.
Appendix: source
Thrown at sources/shaders/Stride.Shaders.Compilers/SpirvTranslator.cs:35
static readonly Cross cross;
static readonly Logger Log = GlobalLogger.GetLogger("SpirvTranslator");
static SpirvTranslator()
{
NativeLibraryHelper.PreloadLibrary("spirv-cross", typeof(SpirvTranslator));
cross = Cross.GetApi();
}
public List<(string RealName, string TranslatedName, ExecutionModel ExecutionModel)> GetEntryPoints(Backend backend = Backend.Hlsl)
{
Context* context = null;
ParsedIr* ir = null;
Compiler* compiler = null;
if (cross.ContextCreate(&context) != Result.Success)
throw new Exception($"{cross.ContextCreate(&context)} : Could not create spirv context");
fixed (uint* w = Words.Span)
if (cross.ContextParseSpirv(context, w, (nuint)Words.Length, &ir) != Result.Success)
throw new Exception($"{cross.ContextParseSpirv(context, w, (nuint)Words.Length, &ir)} : Could not parse spirv");
cross.ContextSetErrorCallback(context, new((void* userData, byte* errorData) =>
{
var error = Marshal.PtrToStringAnsi((IntPtr)errorData);
if (error != null)
Log.Error(error);
}), null);
if (cross.ContextCreateCompiler(context, backend, ir, CaptureMode.Copy, &compiler) != Result.Success)
throw new Exception($"{cross.ContextCreateCompiler(context, backend, ir, CaptureMode.Copy, &compiler)} : could not create compiler");
var result = new List<(string RealName, string TranslatedName, ExecutionModel ExecutionModel)>();
EntryPoint* entry_points = null;
nuint num_entry_points = 0;
cross.CompilerGetEntryPoints(compiler, &entry_points, &num_entry_points);
for (int i = 0; i < (int)num_entry_points; ++i)
{
var entryPointModel = entry_points[i].ExecutionModel;View on GitHub (pinned to 96fad776d2)