{"record":{"id":"347ae7c0f8b87b58","repo":"stride3d/stride","slug":"during-mix-phase-shaders-generics-are-expected-to-be-fully","errorCode":null,"errorMessage":"During mix phase, shaders generics are expected to be fully resolved","messagePattern":"During mix phase, shaders generics are expected to be fully resolved","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"sources/shaders/Stride.Shaders.Parsers/Spirv/Building/Builder.Class.cs","lineNumber":372,"sourceCode":"            var constantBuffer = expr.EmitToBuffer();\n\n            context.RemoveAt(instructionIndex);\n\n            var bound = context.Bound;\n            context.InsertWithoutDuplicates(ref instructionIndex, genericParameter.ResultId, constantBuffer);\n            context.Bound = bound;\n\n            return true;\n        }\n\n        public override void ValidateGenericParameters(string classNameWithGenerics, List<GenericParameter> genericParameters)\n        {\n            // Fully resolved?\n            if (resolveStep == ResolveStep.Mix)\n            {\n                if (!genericParameters.All(x => x.Resolved))\n                {\n                    throw new InvalidOperationException(\"During mix phase, shaders generics are expected to be fully resolved\");\n                }\n            }\n        }\n\n        public override void PostProcess(string classNameWithGenerics)\n        {\n            if (resolveStep == ResolveStep.Mix)\n            {\n                classSource.ClassName = classNameWithGenerics;\n                classSource.GenericArguments = [];\n            }\n        }\n    }\n\n    private static void InstantiateGenericShader(ref ShaderBuffers shaderBuffers, string classNameWithGenerics, GenericResolver genericResolver, IExternalShaderLoader shaderLoader, ReadOnlySpan<ShaderMacro> macros)\n    {\n        var resolvedLinks = new Dictionary<int, string>();\n        var semantics = new Dictionary<string, string>();","sourceCodeStart":354,"sourceCodeEnd":390,"githubUrl":"https://github.com/stride3d/stride/blob/96fad776d210c221682aac1ccdf4c79dc046fc38/sources/shaders/Stride.Shaders.Parsers/Spirv/Building/Builder.Class.cs#L354-L390","documentation":"ValidateGenericParameters enforces that by the Mix resolve step every generic parameter is marked Resolved. If any genericParameters entry still has Resolved == false during mixing, the library throws InvalidOperationException — mixing cannot proceed with unresolved generics because names and constants would be ambiguous.","triggerScenarios":"Running the mixin/mix phase (ResolveStep.Mix) when a generic argument failed to substitute earlier — e.g. a GenericParamExpr that referenced a parent's generic not present in importArgsByName, or an argument that never got a constant value.","commonSituations":"Inheriting from a parameterized mixin whose generic arguments themselves reference generics of an unimported shader; an instantiation that skipped the earlier resolve pass; a bug where resolution silently failed and returned the expression unresolved.","solutions":["Ensure the instantiation supplies concrete constant values for all generics before the mix phase.","Check that every shader referenced in generic expressions is imported so Substitute/ResolveGenericArg can resolve them.","Run the resolve step (ResolveStep.Compile) before mixing so generic parameters get marked Resolved."],"exampleFix":"// before\nBuildInheritanceListIncludingSelf(loader, ctx, source, macros, list, ResolveStep.Mix);\n// after (resolve first, then mix)\nBuildInheritanceListIncludingSelf(loader, ctx, source, macros, list, ResolveStep.Compile);\nBuildInheritanceListIncludingSelf(loader, ctx, source, macros, list, ResolveStep.Mix);","handlingStrategy":"validation","validationCode":"if (resolveStep == ResolveStep.Mix && genericParameters.Any(p => !p.Resolved))\n    throw new InvalidOperationException($\"Unresolved generics before mix: {string.Join(\",\", genericParameters.Where(p => !p.Resolved).Select(p => p.Name))}\");","typeGuard":"bool AllResolved(IEnumerable<GenericParameter> ps) => ps.All(p => p.Resolved);","tryCatchPattern":"try { ValidateGenericParameters(...); }\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"fully resolved\")) { /* rerun the resolve pass before mixing */ }","preventionTips":["Always run a resolve (Compile) pass before the mix phase","Ensure all shaders referenced inside generic expressions are imported","Assert generic resolution immediately after each resolve step in tests"],"tags":["spirv","generics","mix-phase","invariant"],"backgroundTag":"invalid-state-transition","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"}