{"record":{"id":"af5a2ffd70276801","repo":"stride3d/stride","slug":"not-a-spir-v-module","errorCode":null,"errorMessage":"Not a SPIR-V module","messagePattern":"Not a SPIR-V module","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"sources/shaders/Stride.Shaders.Tests/SpirvProbe.cs","lineNumber":45,"sourceCode":"    private const uint DecorationBuiltIn = 11;\n    private const uint DecorationLocation = 30;\n    private const uint DecorationUserSemantic = 5635;\n\n    private const uint StorageClassInput = 1;\n\n    public record EntryPointInfo(uint ExecutionModel, string Name, uint[] Interface);\n\n    public List<EntryPointInfo> EntryPoints { get; } = [];\n    public Dictionary<uint, uint> Locations { get; } = [];\n    public Dictionary<uint, string> UserSemantics { get; } = [];\n    public HashSet<uint> BuiltIns { get; } = [];\n    public Dictionary<uint, uint> VariableStorageClasses { get; } = [];\n\n    public SpirvProbe(ReadOnlySpan<byte> spirv)\n    {\n        var words = MemoryMarshal.Cast<byte, uint>(spirv);\n        if (words.Length < 5 || words[0] != 0x07230203)\n            throw new InvalidOperationException(\"Not a SPIR-V module\");\n\n        for (int i = 5; i < words.Length;)\n        {\n            var wordCount = (int)(words[i] >> 16);\n            var opcode = words[i] & 0xFFFF;\n            if (wordCount == 0)\n                throw new InvalidOperationException(\"Invalid SPIR-V instruction\");\n            var operands = words.Slice(i + 1, wordCount - 1);\n\n            switch (opcode)\n            {\n                case OpEntryPoint:\n                {\n                    var name = ReadString(operands.Slice(2), out var nameWords);\n                    EntryPoints.Add(new EntryPointInfo(operands[0], name, operands.Slice(2 + nameWords).ToArray()));\n                    break;\n                }\n                case OpVariable:","sourceCodeStart":27,"sourceCodeEnd":63,"githubUrl":"https://github.com/stride3d/stride/blob/96fad776d210c221682aac1ccdf4c79dc046fc38/sources/shaders/Stride.Shaders.Tests/SpirvProbe.cs#L27-L63","documentation":"Thrown by the SpirvProbe constructor when the input byte span is too small (<5 words) or its first word is not the SPIR-V magic number 0x07230203. SpirvProbe only parses genuine SPIR-V modules, so malformed input is rejected immediately before any instruction decoding.","triggerScenarios":"new SpirvProbe(bytes) is given bytecode that is actually DXIL, GLSL text, a truncated buffer, or byte-swapped/wrong-endian data, so words[0] != 0x07230203.","commonSituations":"Passing dxbc/dxil output to a SPIR-V pipeline; loading a shader file that failed to compile and contains an error string; reading a file with wrong length (zero bytes); missing the SPIR-V codegen step (e.g. no dxc/spirv backend) so raw HLSL bytes flow through.","solutions":["Ensure the shader is compiled to SPIR-V (dxc -spirv or glslang) before handing the bytes to SpirvProbe.","Check the byte length: a valid module has at least a 20-byte header; log the actual size and first bytes when diagnosing.","Confirm the loaded file is the SPIR-V artifact, not the DXIL/ISKBlob or source text.","If bytes may come from an external source, verify magic 0x03 0x02 0x23 0x07 (little-endian) before constructing the probe."],"exampleFix":"// before\nvar probe = new SpirvProbe(File.ReadAllBytes(\"shader.dxil\"));\n// after\nvar bytes = File.ReadAllBytes(\"shader.spv\");\nif (bytes.Length < 20 || BitConverter.ToUInt32(bytes, 0) != 0x07230203)\n    throw new InvalidOperationException(\"shader.spv is not SPIR-V\");\nvar probe = new SpirvProbe(bytes);","handlingStrategy":"validation","validationCode":"static bool IsSpirv(byte[] bytes)\n    => bytes.Length >= 20 && BitConverter.ToUInt32(bytes, 0) == 0x07230203;","typeGuard":"bool TryAsSpirv(ReadOnlySpan<byte> bytes, out SpirvProbe? probe)\n{\n    probe = null;\n    if (bytes.Length < 20 || BitConverter.ToUInt32(bytes.ToArray(), 0) != 0x07230203)\n        return false;\n    probe = new SpirvProbe(bytes);\n    return true;\n}","tryCatchPattern":"try { var probe = new SpirvProbe(shaderBytes); }\ncatch (InvalidOperationException ex) when (ex.Message == \"Not a SPIR-V module\")\n{\n    // compile the shader to SPIR-V first; log first bytes for diagnosis\n}","preventionTips":["Always run shaders through dxc -spirv / glslang before probing.","Check file size and magic bytes right after loading shader artifacts.","Ensure the build actually produced .spv files (assert in test fixture setup)."],"tags":["spirv","validation","shader-bytecode"],"backgroundTag":"invalid-argument-format","analyzedSha":"96fad776d210c221682aac1ccdf4c79dc046fc38","analyzedAt":"2026-09-14T02:59:31.279Z","contentChangedAt":"2026-09-14T02:59:31.279Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}