microsoft/semantic-kernel · error · ArgumentException
Type '{stepType.FullName}' must be a subclass of KernelProce
Error message
Type '{stepType.FullName}' must be a subclass of KernelProcessStep. What it means
Thrown by the ProcessStepBuilderTyped constructor when the provided stepType does not inherit from KernelProcessStep. All process steps must derive from KernelProcessStep (or its generic KernelProcessStep<TState> variant) so the runtime can manage their lifecycle, state, and function dispatch.
Source
Thrown at dotnet/src/Experimental/Process.Core/ProcessStepBuilder.cs:283
/// </summary>
private object? _initialState;
private readonly Type _stepType;
/// <summary>
/// Creates a new instance of the <see cref="ProcessStepBuilder"/> class. If a name is not provided, the name will be derived from the type of the step.
/// </summary>
/// <param name="stepType">The <see cref="Type"/> of the step.</param>
/// <param name="id">The unique id of the step.</param>
/// <param name="processBuilder">The process builder that this step is a part of.</param>
/// <param name="initialState">Initial state of the step to be used on the step building stage</param>
internal ProcessStepBuilderTyped(Type stepType, string id, ProcessBuilder? processBuilder, object? initialState = default)
: base(id, processBuilder)
{
Verify.NotNull(stepType);
if (!typeof(KernelProcessStep).IsAssignableFrom(stepType))
{
throw new ArgumentException($"Type '{stepType.FullName}' must be a subclass of KernelProcessStep.", nameof(stepType));
}
this._stepType = stepType;
this.FunctionsDict = this.GetFunctionMetadataMap();
this._initialState = initialState;
}
/// <summary>
/// Builds the step with a state if provided
/// </summary>
/// <returns>An instance of <see cref="KernelProcessStepInfo"/></returns>
internal override KernelProcessStepInfo BuildStep(ProcessBuilder processBuilder, KernelProcessStepStateMetadata? stateMetadata = null)
{
KernelProcessStepState? stateObject = null;
KernelProcessStepMetadataAttribute stepMetadataAttributes = KernelProcessStepMetadataFactory.ExtractProcessStepMetadataFromType(this._stepType);
if (this._stepType.TryGetSubtypeOfStatefulStep(out Type? genericStepType) && genericStepType is not null)
{View on GitHub (pinned to c028a0c7dc)
Solutions
- Make the step class inherit from KernelProcessStep (or KernelProcessStep<TState> for custom state).
- If the type comes from an external assembly, verify it derives from KernelProcessStep before registering it.
- Use AddStepFromType<TConcreteStep>() with the generic overload where possible to get compile-time safety.
Example fix
// before
public class MyWorker // does not inherit KernelProcessStep
{
[KernelFunction]
public void DoWork() { }
}
process.AddStepFromType(typeof(MyWorker)); // throws
// after
public class MyWorker : KernelProcessStep
{
[KernelFunction]
public void DoWork() { }
}
process.AddStepFromType<MyWorker>(); Defensive patterns
Strategy: type-guard
Validate before calling
if (!typeof(KernelProcessStep).IsAssignableFrom(stepType))
throw new ArgumentException(
$"Type '{stepType.FullName}' must inherit from KernelProcessStep.", nameof(stepType));
process.AddStepFromType(stepType); Type guard
bool IsValidStepType(Type stepType) => typeof(KernelProcessStep).IsAssignableFrom(stepType);
Prevention
- Prefer the generic AddStepFromType<T>() overload for compile-time type safety.
- When loading step types dynamically, filter by typeof(KernelProcessStep).IsAssignableFrom before registration.
- Ensure step classes explicitly inherit from KernelProcessStep or KernelProcessStep<TState>.
When it happens
Trigger: Calling AddStepFromType with a type that is not a subclass of KernelProcessStep; passing a plain POCO class or a class inheriting from a different base; using reflection to provide a step type that doesn't meet the constraint.
Common situations: Trying to use a regular service class or DTO as a process step; migrating from a non-process framework and forgetting to add the KernelProcessStep base class; dynamically loading step types from assemblies where some types are not valid steps; misunderstanding the process step contract.
Related errors
- The step {this.Name} has no functions.
- The step {this.Name} has more than one function, so a functi
- The target step {this.Name} has no functions.
- The target step has more than one function, so a function na
- The function {functionName} does not exist on step {this.Nam
AI-assisted analysis of microsoft/semantic-kernel@c028a0c7dc (2026-08-13).
Data as JSON: /api/errors/8d991c33a8424b99.
Report an issue: GitHub.