{"record":{"id":"74aee6fbd197b2d9","repo":"stride3d/stride","slug":"swizzle-accessors-i-is-out-of-bound-for-expression-tostring","errorCode":null,"errorMessage":"Swizzle {Accessors[i]} is out of bound for expression {ToString(i)} of type {vectorOrScalarType}","messagePattern":"Swizzle (.+?) is out of bound for expression (.+?) of type (.+?)","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"sources/shaders/Stride.Shaders.Parsers/Parsing/SDSL/AST/Expression.cs","lineNumber":917,"sourceCode":"                && currentValueType is PointerType { BaseType: VectorType or ScalarType } or VectorType or ScalarType\n                && Accessors[i] is Identifier { Name: var swizzle1 } id1 && id1.IsVectorSwizzle()\n                && Accessors[i + 1] is Identifier { Name: var swizzle2 } id2 && id2.IsVectorSwizzle())\n            {\n                var vectorOrScalarType = currentValueType is PointerType p ? p.BaseType : currentValueType;\n\n                (var size, ScalarType baseType) = vectorOrScalarType switch\n                {\n                    ScalarType s => (1, s),\n                    VectorType v => (v.Size, v.BaseType),\n                    _ => throw new NotSupportedException($\"Unsupported type {vectorOrScalarType} for swizzle coalescing\"),\n                };\n\n                var swizzleIndices = new int[swizzle1.Length];\n                for (int j = 0; j < swizzle1.Length; ++j)\n                {\n                    swizzleIndices[j] = ConvertSwizzle(swizzle1[j]);\n                    if (swizzleIndices[j] >= size)\n                        throw new InvalidOperationException($\"Swizzle {Accessors[i]} is out of bound for expression {ToString(i)} of type {vectorOrScalarType}\");\n                }\n\n                // Combine swizzles with previous ones\n                var newSwizzleIndices = new int[swizzle2.Length];\n                for (int j = 0; j < swizzle2.Length; ++j)\n                {\n                    newSwizzleIndices[j] = swizzleIndices[ConvertSwizzle(swizzle2[j])];\n                    if (newSwizzleIndices[j] >= size)\n                        throw new InvalidOperationException($\"Swizzle {Accessors[i + 1]} is out of bound for expression {ToString(i)} of type {currentValueType}\");\n                }\n\n                Accessors.RemoveAt(i + 1);\n                Span<char> vectorFields = ['x', 'y', 'z', 'w'];\n                Span<char> newSwizzle = stackalloc char[swizzle2.Length];\n                for (int j = 0; j < swizzle2.Length; ++j)\n                {\n                    newSwizzle[j] = vectorFields[newSwizzleIndices[j]];\n                }","sourceCodeStart":899,"sourceCodeEnd":935,"githubUrl":"https://github.com/stride3d/stride/blob/96fad776d210c221682aac1ccdf4c79dc046fc38/sources/shaders/Stride.Shaders.Parsers/Parsing/SDSL/AST/Expression.cs#L899-L935","documentation":"During swizzle coalescing, each character of the first swizzle is converted to an index; if that index is >= the vector's component size, the swizzle reads components that don't exist, so an InvalidOperationException is thrown naming the accessor and expression type.","triggerScenarios":"A shader expression like float2 v; v.xz where swizzle index (z=2) >= size (2) — i.e. any swizzle accessor beyond the vector's dimension, encountered while merging nested swizzles in Expression.cs.","commonSituations":"Copy-pasted GLSL code assuming vec4-sized swizzles on a vec2/vec3; dynamic shader generation producing invalid swizzle letters.","solutions":["Fix the swizzle letters so all indices are within the vector size (e.g. v.xy for a float2)","Verify the declared type of the variable and adjust the swizzle accordingly","Add a static/validation pass to reject out-of-bounds swizzles before codegen"],"exampleFix":"// before\nfloat2 v; float f = v.z;\n// after\nfloat2 v; float f = v.y;","handlingStrategy":"validation","validationCode":"bool valid = swizzle.All(c => \"xyzw\".IndexOf(c) < vectorSize) && swizzle.All(c => c is 'x' or 'y' or 'z' or 'w');","typeGuard":"bool SwizzleInBounds(string swizzle, int size) => swizzle.All(c => \"xyzw\".IndexOf(c) < size);","tryCatchPattern":"try { Compile(expr); } catch (InvalidOperationException e) when (e.Message.Contains(\"is out of bound\")) { ReportSwizzleError(expr, e.Message); }","preventionTips":["Validate swizzle letters against vector component counts at authoring time","Enable editor/analyzer checks for SDSL swizzle usage","Use explicit types in shaders so vector sizes are clear"],"tags":["sdsl","shader","swizzle","out-of-range"],"backgroundTag":"index-out-of-bounds","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"}