stride3d/stride · error · InvalidOperationException

ResourceGroup has no ResourceGroupSDSL name decoration

Error message

ResourceGroup {groupId} has no ResourceGroupSDSL name decoration

What it means

StreamAnalyzer.Analyze groups resources by their ResourceGroup id. Each group id must have an OpName/ResourceGroupSDSL name decoration recorded in groupNames; when a target references a group id with no recorded name, the analyzer cannot construct the ResourceGroup and throws InvalidOperationException.

Solutions

  1. Ensure every ResourceGroup id gets a ResourceGroupSDSL name decoration before Analyze runs
  2. Check pass ordering: the naming pass must execute before StreamAnalyzer.Analyze
  3. Verify groupNames is populated from the right decoration type/key for the groupId
  4. Inspect which groupId is missing a name (printed in the message) and find the transformation that created it

Example fix

// before
group MyResources : ResourceGroupSDSL { } // name decoration missing for the id used
// after
group MyResources : ResourceGroupSDSL { Texture2D tex; }; // ensure group is declared and decorated so groupNames contains its id
Defensive patterns

Strategy: validation

Validate before calling

foreach (var groupId in groupIdByTarget.Values)
    if (!groupNames.ContainsKey(groupId)) throw new InvalidOperationException($"ResourceGroup {groupId} is missing a ResourceGroupSDSL name decoration");

Try / catch

try { analyzer.Analyze(module); } catch (InvalidOperationException ex) { logger.LogError(ex, "Undecorated resource group"); throw new ShaderCompilationException("Resource group name decoration missing", ex); }

Prevention

When it happens

Trigger: A descriptor/OpDecorate pipeline associates a resource with a ResourceGroup id for which no ResourceGroupSDSL name decoration was emitted — e.g. decorations stripped, order of analysis passes wrong, or a group created implicitly by a transformation without naming it.

Common situations: Upstream passes renaming/removing OpName decorations before StreamAnalyzer runs; shader code or transformations creating descriptor sets without explicit group names; mismatched decoration keys (groupId vs target).

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


AI-assisted analysis of stride3d/stride@96fad776d2 (2026-09-14). Data as JSON: /api/errors/55bca9ff74223dfd. Report an issue: GitHub.

Appendix: source

Thrown at sources/shaders/Stride.Shaders.Parsers/Spirv/Processing/Interfaces/Analysis/StreamAnalyzer.cs:162

                groupIdByTarget.TryAdd(resourceGroupIdDecorate.Target, m.To<DecorationParams.ResourceGroupIdSDSL>().ResourceGroup);
        }

        // Resolve group ID → name (first target with both a group ID and a ResourceGroupSDSL name wins)
        Dictionary<int, string> groupNames = new();
        foreach (var (target, groupId) in groupIdByTarget)
        {
            if (!groupNames.ContainsKey(groupId) && resourceGroupNamesByTarget.TryGetValue(target, out var name))
                groupNames.Add(groupId, name);
        }

        // Build ResourceGroups and assign resources/cbuffers
        Dictionary<int, ResourceGroup> resourceGroups = new();
        foreach (var (target, groupId) in groupIdByTarget)
        {
            if (!resourceGroups.TryGetValue(groupId, out var resourceGroup))
            {
                if (!groupNames.TryGetValue(groupId, out var name))
                    throw new InvalidOperationException($"ResourceGroup {groupId} has no ResourceGroupSDSL name decoration");
                resourceGroups.Add(groupId, resourceGroup = new(name));
            }

            if (resources.TryGetValue(target, out var resourceInfo))
            {
                resourceGroup.Resources.Add(resourceInfo);
                resourceInfo.ResourceGroup = resourceGroup;
            }
            else if (cbuffers.TryGetValue(target, out var cbufferInfo))
            {
                cbufferInfo.ResourceGroup = resourceGroup;
            }

            // Apply LogicalGroup if present
            if (logicalGroupNamesByTarget.TryGetValue(target, out var logicalGroup))
            {
                resourceGroup.LogicalGroup ??= logicalGroup;
                if (cbuffers.TryGetValue(target, out var ci))

View on GitHub (pinned to 96fad776d2)