stride3d/stride · error · InvalidOperationException

Parameter ( ) in method doesn't have a default but a…

Error message

Parameter {index} ({arg.Name}) in method {Name} doesn't have a default but a previous argument had a default value

What it means

Method parameters with default values must form a contiguous trailing block, as in C#. Once a parameter has a DefaultValue, every following parameter must also have one; otherwise the compiler cannot build valid default-argument elision and throws this InvalidOperationException.

Solutions

  1. Give the offending parameter a default value.
  2. Reorder parameters so all defaulted ones come last.
  3. Remove the default from the earlier parameter.

Example fix

// before
void Foo(float a = 1.0, float b);
// after
void Foo(float a = 1.0, float b = 2.0);
Defensive patterns

Strategy: validation

Validate before calling

bool seenDefault = false;
foreach (var p in method.Parameters)
{
    if (seenDefault && p.DefaultValue == null) throw new InvalidOperationException("Default parameters must be trailing");
    seenDefault |= p.DefaultValue != null;
}

Try / catch

try { method.ProcessSymbol(table, context); }
catch (InvalidOperationException ex) when (ex.Message.Contains("doesn't have a default"))
{
    // supply the missing default or reorder parameters
}

Prevention

When it happens

Trigger: Declaring a shader method like `void Foo(float a = 1, float b)` where a parameter after a defaulted one lacks a default.

Common situations: Reordering parameters during refactoring so a defaulted argument precedes a non-defaulted one, or appending a new non-defaulted parameter to a method that already had defaults.

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/bf6b3dc2557ec229. Report an issue: GitHub.

Appendix: source

Thrown at sources/shaders/Stride.Shaders.Parsers/Parsing/SDSL/AST/ShaderElements.MethodOrMember.cs:435

        {
            p.TypeName.ProcessSymbol(table);
            var argSym = p.TypeName.Type!;
            table.DeclaredTypes.TryAdd(argSym.ToString(), argSym);
            p.Type = argSym;
            var parameterType = GenerateParameterType(p);
            ftype.ParameterTypes.Add(new(parameterType, p.Modifiers));
            var parameterSymbol = new Symbol(new(p.Name, SymbolKind.Variable), parameterType, 0, OwnerType: table.CurrentShader);
            table.CurrentFrame.Add(p.Name, parameterSymbol);
            ParameterSymbols.Add(parameterSymbol);
        }

        Span<int> defaultParameters = stackalloc int[Parameters.Count];
        var firstDefaultParameter = -1;
        for (var index = 0; index < Parameters.Count; index++)
        {
            var arg = Parameters[index];
            if (firstDefaultParameter != -1 && arg.DefaultValue == null)
                throw new InvalidOperationException($"Parameter {index} ({arg.Name}) in method {Name} doesn't have a default but a previous argument had a default value");
            if (arg.DefaultValue != null)
            {
                if (firstDefaultParameter == -1)
                    firstDefaultParameter = index;
                defaultParameters[index] = arg.DefaultValue.CompileConstantValue(table, context, arg.Type).Id;
            }

            if (arg.Semantic != null)
            {
                // We use OpMemberDecorateString on the function ID
                // but this is not valid so we'll need to make sure to remove that after the ShaderMixer
                context.Add(new OpMemberDecorateString(function.Id, index, Specification.Decoration.UserSemantic, arg.Semantic));
            }
        }

        var symbol = new Symbol(new(Name, SymbolKind.Method, IsStage: IsStaged), ftype, function.Id, MemberAccessWithImplicitThis: ftype, OwnerType: table.CurrentShader);

        if (firstDefaultParameter != -1)

View on GitHub (pinned to 96fad776d2)