{"record":{"id":"45338da2b855352f","repo":"stride3d/stride","slug":"use-of-undeclared-stream-variable-streamvar-name","errorCode":null,"errorMessage":"Use of undeclared stream variable '{streamVar.Name}'","messagePattern":"Use of undeclared stream variable '(.+?)'","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"sources/shaders/Stride.Shaders.Parsers/Parsing/SDSL/AST/Expression.cs","lineNumber":1129,"sourceCode":"                        }\n\n                        var (builder, context) = compiler;\n                        var importedVariable = ShaderDefinition.ImportSymbol(table, context, field.ResolvedSymbol!);\n\n                        // Emit OpAccessChain with everything so far\n                        EmitOpAccessChain(accessChainIds, i - 1);\n\n                        // TODO: figure out instance (this vs composition)\n                        result = IdentifierBase.EmitSymbol(builder, context, importedVariable, false, result.Id);\n                        break;\n                    }\n                case (PointerType { BaseType: StreamsType s } p, Identifier streamVar):\n                    if (compiler == null)\n                    {\n                        streamVar.AllowStreamVariables = true;\n                        streamVar.ProcessSymbol(table);\n                        if (streamVar.Type is not PointerType)\n                            throw new InvalidOperationException($\"Use of undeclared stream variable '{streamVar.Name}'\");\n                        accessor.Type = (PointerType)streamVar.Type with { StorageClass = p.StorageClass };\n                        break;\n                    }\n\n                    // We emit chain access so far\n                    // It's not necessary for SPIR-V, but StreamAccessPatcher.PatchStreamsAccesses() expect a simple format without\n                    // multiple access chained (which make it harder to compute type)\n                    EmitOpAccessChain(accessChainIds, i - 1);\n\n                    // Since we cheated a bit by overwriting the accessor.Type, set it back during Compile()\n                    accessor.Type = (PointerType)accessor.Type! with { StorageClass = Specification.StorageClass.Private };\n                    // Since STREAMS struct is built later for each shader, we simply make a reference to variable for now\n                    var streamVariableResult = streamVar.Compile(table, compiler);\n                    accessor.Type = (PointerType)accessor.Type! with { StorageClass = p.StorageClass };\n                    PushAccessChainId(accessChainIds, streamVariableResult.Id);\n\n                    // For same reason as before (we want easy to detect pattern for StreamAccessPatcher), emit again\n                    currentValueType = accessor.Type!;","sourceCodeStart":1111,"sourceCodeEnd":1147,"githubUrl":"https://github.com/stride3d/stride/blob/96fad776d210c221682aac1ccdf4c79dc046fc38/sources/shaders/Stride.Shaders.Parsers/Parsing/SDSL/AST/Expression.cs#L1111-L1147","documentation":"When a stream pointer is indexed with an identifier (e.g. stream var access during type processing, compiler == null), the compiler lets the identifier resolve stream variables. If after ProcessSymbol the identifier's type is not a PointerType, the symbol wasn't a declared stream variable, so this error is thrown. It indicates a reference to a name that is not a known stream in the stream-access chain.","triggerScenarios":"Indexing a StreamsType pointer with an Identifier whose ProcessSymbol resolution yields a non-pointer type — i.e. the name does not refer to a declared stream variable.","commonSituations":"Typos in stream variable names inside geometry shader stream-access expressions, referring to a stream before its declaration, or accessing a stream from a stage/effect where it was never declared as a stream.","solutions":["Check spelling of the stream variable name against the declared streams in the shader signature.","Ensure the stream variable is declared (as a stream/in/out with StreamsType) before it is accessed.","Verify you are in a geometry-stream stage context where stream variables are valid."],"exampleFix":"// before\nouputStream.Append(v);          // typo, undeclared\n\n// after\noutputStream.Append(v);         // matches the declared stream variable","handlingStrategy":"validation","validationCode":"// check the identifier refers to a declared stream before accessing\nvar sym = table.TryLookup(streamName);\nif (sym?.Type is not PointerType)\n    throw new InvalidOperationException($\"'{streamName}' is not a declared stream variable\");","typeGuard":"static bool IsStreamVariable(Symbol s) => s?.Type is PointerType { BaseType: StreamsType };","tryCatchPattern":"try { CompileShader(source); }\ncatch (InvalidOperationException e) when (e.Message.StartsWith(\"Use of undeclared stream variable\"))\n{\n    // fix the stream name or declare the stream\n}","preventionTips":["Verify stream variable names against the shader signature before use.","Declare streams before any access in the shader body.","Only reference stream variables inside stages that support stream access (e.g. geometry)."],"tags":["shader","sdsl","streams","undeclared-identifier"],"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"}