{"record":{"id":"c118d1c793accb1c","repo":"stride3d/stride","slug":"constant-name-doesn-t-have-a-value","errorCode":null,"errorMessage":"Constant {Name} doesn't have a value","messagePattern":"Constant (.+?) doesn't have a value","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"sources/shaders/Stride.Shaders.Parsers/Parsing/SDSL/AST/ShaderElements.MethodOrMember.cs","lineNumber":223,"sourceCode":"            var bufTypeName = memberType is AppendStructuredBufferType ? \"AppendStructuredBuffer\" : \"ConsumeStructuredBuffer\";\n            table.AddError(new(TypeName.Info, $\"{bufTypeName} is not supported. Use RWStructuredBuffer with a separate counter buffer instead (variable '{Name}').\"));\n            return;\n        }\n\n        var storageClass = (memberType, StorageClass, StreamKind) switch\n        {\n            (TextureType or BufferType, _, _) => Specification.StorageClass.UniformConstant,\n            (StructuredBufferType or ByteAddressBufferType, _, _) => Specification.StorageClass.StorageBuffer,\n            (_, StorageClass.GroupShared, _) => Specification.StorageClass.Workgroup,\n            (_, StorageClass.Static, _) => Specification.StorageClass.Private,\n            (_, _, StreamKind.Stream or StreamKind.PatchStream) => Specification.StorageClass.Private,\n            _ => Specification.StorageClass.Uniform,\n        };\n\n        if (TypeModifier == TypeModifier.Const)\n        {\n            if (Value == null)\n                throw new InvalidOperationException($\"Constant {Name} doesn't have a value\");\n\n            // Constant: compile right away\n            var constantValue = Value.CompileConstantValue(table, context, memberType);\n            // Infer size for unsized arrays (e.g. `static const uint info[] = {...};`) from\n            // the initializer; otherwise indexing the constant later allocates a temp variable\n            // typed as runtime array, mismatching the OpSpecConstantComposite's sized OpTypeArray.\n            if (memberType is ArrayType { Size: -1 } && Value.ValueType is ArrayType { Size: > 0 } inferred)\n                memberType = inferred;\n            context.SetName(constantValue.Id, Name);\n            var constant = new Symbol(new(Name, SymbolKind.Constant), memberType, constantValue.Id, OwnerType: table.CurrentShader);\n            table.CurrentFrame.Add(Name, constant);\n            Type = memberType;\n\n            // This constant is visible when inherited (name stored in decoration to avoid dedup conflicts)\n            context.Add(new OpDecorateString(constantValue.Id, Specification.Decoration.ShaderConstantSDSL, Name));\n        }\n        else\n        {","sourceCodeStart":205,"sourceCodeEnd":241,"githubUrl":"https://github.com/stride3d/stride/blob/96fad776d210c221682aac1ccdf4c79dc046fc38/sources/shaders/Stride.Shaders.Parsers/Parsing/SDSL/AST/ShaderElements.MethodOrMember.cs#L205-L241","documentation":"A field declared with the const TypeModifier must have an initializer. The compiler compiles constants immediately during ProcessSymbol and needs the initializer to produce a constant/spec-constant value, so a const field with Value == null throws this InvalidOperationException.","triggerScenarios":"Declaring `const float x;` (or `static const uint arr[];`) in a shader with no assignment, then compiling the shader.","commonSituations":"Forward-declaring constants out of C/C++ habit, or a refactoring that removed the initializer expression.","solutions":["Add an initializer to the const field, e.g. `const float x = 1.0;`.","Remove the const modifier if the value is meant to be assigned at runtime.","For unsized const arrays, supply a full initializer list so the size can be inferred."],"exampleFix":"// before\nconst float Scale;\n// after\nconst float Scale = 2.0;","handlingStrategy":"validation","validationCode":"foreach (var f in shader.Fields)\n    if (f.TypeModifier == TypeModifier.Const && f.Value == null)\n        throw new InvalidOperationException($\"const field {f.Name} needs an initializer\");","typeGuard":null,"tryCatchPattern":"try { field.ProcessSymbol(table, context); }\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"doesn't have a value\"))\n{\n    // add an initializer or drop the const modifier\n}","preventionTips":["Always initialize const fields at declaration.","Remove const from fields whose value is computed or assigned at runtime."],"tags":["shader","sdsl","constants","validation"],"backgroundTag":"missing-required-argument","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"}