elsa-workflows/elsa-core · error · InvalidOperationException

Unexpected non-optional, non-Input

Error message

Unexpected non-optional, non-Input<T> parameter '{param.Name}' in constructor for '{activityType.Name}'

What it means

After selecting a constructor, the compiler fills Input<T> parameters from arguments and skips optional parameters using their defaults. If it encounters a required (non-optional) parameter that is not Input<T>, it cannot supply a value and throws this InvalidOperationException. The message notes this 'shouldn't happen if filtering is correct', marking an unexpected activity constructor shape.

Solutions

  1. Rewrite the activity constructor so all required parameters are Input<T> types
  2. Give non-Input parameters default values so they are treated as optional
  3. Use named arguments targeting only Input<T> parameters, avoiding the offending constructor
  4. Wrap or adapt the third-party activity with an Elsa-compatible constructor

Example fix

// before
public MyActivity(string name, Input<string> text) { ... }
// after
public MyActivity(Input<string> name, Input<string> text) { ... }
Defensive patterns

Strategy: type-guard

Validate before calling

bool HasOnlyInputOrOptionalParams(ConstructorInfo c) =>
    c.GetParameters().All(p => IsInputType(p.ParameterType) || p.HasDefaultValue);

Type guard

static bool IsValidActivityConstructor(ConstructorInfo c) =>
    c.GetParameters().All(p => typeof(IInput).IsAssignableFrom(p.ParameterType) || p.HasDefaultValue);

Prevention

When it happens

Trigger: An activity constructor mixes required non-Input parameters (e.g. a required string or service parameter without a default) alongside Input<T> parameters, and that constructor is selected during positional invocation.

Common situations: Custom activities written with plain required constructor parameters instead of Input<T>; third-party activities not designed for ElsaScript constructor instantiation.

Related errors


AI-assisted analysis of elsa-workflows/elsa-core@fe9217bdfa (2026-09-13). Data as JSON: /api/errors/76d453670ef48b45. Report an issue: GitHub.

Appendix: source

Thrown at src/modules/Elsa.Dsl.ElsaScript/Compiler/ElsaScriptCompiler.cs:591

            // Check if this is one of our Input<T> parameters
            var inputParamIndex = Array.IndexOf(selectedInputParams, param);

            if (inputParamIndex >= 0)
            {
                // This is an Input<T> parameter - compile the corresponding positional argument
                var arg = positionalArgs[inputParamIndex];
                var value = CompileExpression(arg.Value, param.ParameterType);
                ctorArgs.Add(value);
            }
            else if (param.IsOptional)
            {
                // This is an optional parameter (like CallerFilePath) - use its default value
                ctorArgs.Add(param.DefaultValue);
            }
            else
            {
                // This shouldn't happen if our filtering is correct
                throw new InvalidOperationException(
                    $"Unexpected non-optional, non-Input<T> parameter '{param.Name}' in constructor for '{activityType.Name}'");
            }
        }

        // Instantiate the activity using the constructor
        var activity = (IActivity)selectedCtor.Invoke(ctorArgs.ToArray());
        return activity;
    }

    private static string MapLanguageName(string dslLanguage) =>
        LanguageMappings.TryGetValue(dslLanguage, out var mapped) ? mapped : dslLanguage;
}

View on GitHub (pinned to fe9217bdfa)