{"record":{"id":"0e77fcf25aafee60","repo":"stride3d/stride","slug":"spirv-magic-number-not-found-spirvbytecode","errorCode":null,"errorMessage":"SPIRV Magic number not found","messagePattern":"SPIRV Magic number not found","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"sources/shaders/Stride.Shaders.Spirv/Buffers/SpirvBytecode.cs","lineNumber":40,"sourceCode":"                bound = index + 1;\n        }\n        return new SpirvHeader(\"1.4\", 0, bound);\n    }\n\n    public Span<byte> ToSpan()\n    {\n        return CreateBytecodeFromBuffers(Header, false, Buffer);\n    }\n\n    public static SpirvBytecode CreateFromSpan(Span<byte> span)\n    {\n        return CreateFromSpan(MemoryMarshal.Cast<byte, int>(span));\n    }\n\n    public static SpirvBytecode CreateFromSpan(Span<int> span)\n    {\n        if (span[0] != Specification.MagicNumber)\n            throw new InvalidOperationException(\"SPIRV Magic number not found\");\n\n        var header = SpirvHeader.Read(span);\n\n        return new(header, new SpirvBuffer(span[SpirvHeader.IntSpanSize..]));\n    }\n\n    // Returns a freshly allocated array. Do not back this with ArrayPool/SpanOwner: the caller\n    // receives a Span that carries no ownership, so a pooled buffer would be returned to the pool\n    // by the finalizer and reused while the span is still in use, silently corrupting the bytecode\n    // (e.g. another shader's OpCapability bleeding into vkCreateShaderModule input).\n    public static Span<int> CreateSpanFromBuffers(SpirvHeader header, bool computeBounds, params Span<SpirvBuffer> buffers)\n    {\n        int instructionsMemorySize = 0;\n        var bound = header.Bound;\n        foreach (var buffer in buffers)\n        {\n            foreach (var i in buffer)\n            {","sourceCodeStart":22,"sourceCodeEnd":58,"githubUrl":"https://github.com/stride3d/stride/blob/96fad776d210c221682aac1ccdf4c79dc046fc38/sources/shaders/Stride.Shaders.Spirv/Buffers/SpirvBytecode.cs#L22-L58","documentation":"SpirvBytecode.CreateFromSpan validates that the first 32-bit word of the buffer equals the SPIR-V magic number 0x07230203 before parsing the header. If the data does not start with that magic, the span is not SPIR-V bytecode and parsing would produce garbage, so it throws immediately.","triggerScenarios":"Calling CreateFromSpan(byte[]/Span<byte>) or CreateFromSpan(Span<int>) with data that is not SPIR-V: raw HLSL/GLSL text, a D3D bytecode blob (DXBC), a truncated buffer, a byte-order/endian-mangled blob, or an offset into a larger file that skips the header.","commonSituations":"Passing compiled DXBC instead of SPIR-V; passing shader source text; reading a shader cache file with a container header still attached; a save/load pipeline that trims or re-orders bytes; platform endianness differences when filling the int span.","solutions":["Verify the input actually is SPIR-V: check the first four bytes are 0x03 0x02 0x23 0x07 before calling CreateFromSpan","Ensure you pass the SPIR-V module itself, not a container or source text; strip any wrapping header first","Confirm the byte->int cast uses correct endianness (little-endian words) and that no offset shifted the start of the module"],"exampleFix":"// before\nvar bytecode = SpirvBytecode.CreateFromSpan(File.ReadAllBytes(\"shader.fxc\")); // DXBC, not SPIR-V\n// after\nvar bytes = File.ReadAllBytes(\"shader.spv\");\nif (bytes.Length >= 4 && bytes[0] == 0x03 && bytes[1] == 0x02 && bytes[2] == 0x23 && bytes[3] == 0x07)\n    var bytecode = SpirvBytecode.CreateFromSpan(bytes);","handlingStrategy":"validation","validationCode":"static bool LooksLikeSpirv(ReadOnlySpan<byte> bytes) =>\n    bytes.Length >= 4 && bytes[0] == 0x03 && bytes[1] == 0x02 && bytes[2] == 0x23 && bytes[3] == 0x07;\n\nif (!LooksLikeSpirv(bytes))\n    throw new InvalidDataException(\"Input is not SPIR-V (magic number 0x07230203 missing).\");","typeGuard":"static bool IsSpirvMagic(Span<int> words) => words.Length > 0 && words[0] == 0x07230203;","tryCatchPattern":"try\n{\n    var bytecode = SpirvBytecode.CreateFromSpan(span);\n}\ncatch (InvalidOperationException ex) when (ex.Message == \"SPIRV Magic number not found\")\n{\n    log.Error(\"Input blob is not SPIR-V bytecode (bad magic); check the source container/format.\");\n}","preventionTips":["Verify the first 4 bytes (0x03 0x02 0x23 0x07) before parsing","Never pass DXBC/GLSL text/container-prefixed blobs to CreateFromSpan","Persist a format tag alongside cached shaders so SPIR-V blobs are identifiable","Watch endianness when building the int span on non-little-endian platforms"],"tags":["spirv","bytecode","magic-number","invalid-input"],"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"}