{"record":{"id":"e4a29172c6e3b254","repo":"stride3d/stride","slug":"struct-importstruct-structname-not-found-in-shader","errorCode":null,"errorMessage":"Struct {importStruct.StructName} not found in shader {shaderName}","messagePattern":"Struct (.+?) not found in shader (.+?)","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"sources/shaders/Stride.Shaders.Compilers/SDSL/ShaderMixer.cs","lineNumber":616,"sourceCode":"\n                // Detect when we switch from context to main buffer\n                if (i2.Op == Op.OpShaderSDSL)\n                {\n                    isContext = false;\n                }\n\n                // Specific type instructions in context gets deduplicated before adding\n                bool addToContext = false;\n                if (TypeDuplicateHelper.OpCheckDuplicateForTypesAndImport(i2.Op))\n                {\n                    // We need to replace those right now (otherwise further types depending on this struct won't get properly translated)\n                    if (i2.Op == Op.OpImportStructSDSL && new OpImportStructSDSL(ref i2) is { } importStruct)\n                    {\n                        var shaderName = globalContext.ExternalShaders[importStruct.Shader];\n                        var shader2 = mixinNode.ShadersByName[shaderName];\n                        if (!shader2.StructTypes.TryGetValue(importStruct.StructName, out var structId)\n                            && (shader2.Stage == null || !shader2.Stage.StructTypes.TryGetValue(importStruct.StructName, out structId)))\n                            throw new InvalidOperationException($\"Struct {importStruct.StructName} not found in shader {shaderName}\");\n                        remapIds.Add(importStruct.ResultId, structId);\n                        removedIds.Add(structId);\n                    }\n                    else\n                    {\n                        // Check if type already exists in context (deduplicate them)\n                        if (typeDuplicateInserter.CheckForDuplicates(i2, out var existingInstruction))\n                        {\n                            if (i2.IdResult is int duplicateId)\n                            {\n                                remapIds.Add(duplicateId, existingInstruction.Data.IdResult!.Value);\n                                var mismatches = typeDuplicateInserter.MergeTypeDecorations(existingInstruction.Data.IdResult.Value, duplicateId);\n                                if (mismatches != null)\n                                {\n                                    var details = string.Join(\"; \", mismatches.Select(m =>\n                                        $\"{m.Data} (only on {(m.OnKeepOnly ? \"kept\" : \"removed\")} type)\"));\n                                    globalContext.Log.Warning($\"Mismatched decorations when merging type {duplicateId} into {existingInstruction.Data.IdResult.Value}: {details}\");\n                                    foreach (var entry in mismatches)","sourceCodeStart":598,"sourceCodeEnd":634,"githubUrl":"https://github.com/stride3d/stride/blob/96fad776d210c221682aac1ccdf4c79dc046fc38/sources/shaders/Stride.Shaders.Compilers/SDSL/ShaderMixer.cs#L598-L634","documentation":"During SDSL shader mixing, an OpImportStructSDSL instruction imports a struct type declared in another shader referenced via the external shaders context. The mixer looks the struct up in the target shader's own StructTypes and, failing that, in its associated Stage's StructTypes. If the struct is declared in neither, the shader composition is invalid and merging aborts.","triggerScenarios":"ShaderMixer.MergeClassInBuffers encounters an OpImportStructSDSL whose Shader index resolves (via globalContext.ExternalShaders) to a shader that does not declare a struct named importStruct.StructName in ShaderInfo.StructTypes or its Stage.StructTypes.","commonSituations":"Renaming or deleting a struct in a base shader while dependent shaders still import it; misspelling the struct name in the import; importing from a shader that only declares the struct in a different mixin/stage not attached here; stale compiled shader classes after refactoring SDSL sources.","solutions":["Ensure the struct with the exact name exists in the shader being imported from (or in its Stage's StructTypes).","Fix the struct name in the import statement to match the declaration.","Check that globalContext.ExternalShaders maps importStruct.Shader to the intended shader.","Rebuild/clean shader compilation caches after refactoring shader code."],"exampleFix":"// before (shader B imports a struct that no longer exists)\nimport Struct ShadowParameters from A;\n// after (re-add the struct in shader A or correct the name)\nstruct ShadowParameters { float bias; }; // in shader A\n// or: import Struct ShadowParams from A; // matching A's actual struct name","handlingStrategy":"validation","validationCode":"// Before composing, verify the imported struct exists in the source shader\nif (!sourceShader.StructTypes.ContainsKey(importedStructName) &&\n    (sourceShader.Stage == null || !sourceShader.Stage.StructTypes.ContainsKey(importedStructName)))\n    throw new InvalidOperationException($\"Struct '{importedStructName}' missing in '{shaderName}' before mixing\");","typeGuard":null,"tryCatchPattern":"// Wrap shader mixing during content/asset build\nclass ShaderMixException : Exception\n{\n    public ShaderMixException(string shader, string structName, Exception inner)\n        : base($\"Failed to mix '{shader}': missing struct '{structName}'. Check import declarations.\", inner) { }\n}\ntry { var result = mixer.Merge(...); }\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"not found in shader\"))\n{ throw new ShaderMixException(shaderName, structName, ex); }","preventionTips":["Keep struct declarations and their imports in sync; search for import sites when renaming a struct.","Use a shared common shader file for structs imported across multiple shaders.","Recompile all shaders after refactoring SDSL sources; never mix stale compiled modules.","Add a unit test that composes every shader class in the project to catch missing imports early."],"tags":["shader","sdsl","compilation","type-not-found"],"backgroundTag":"resource-not-found","analyzedSha":"96fad776d210c221682aac1ccdf4c79dc046fc38","analyzedAt":"2026-09-14T02:59:31.279Z","contentChangedAt":"2026-09-14T02:59:31.279Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}