{"record":{"id":"8d991c33a8424b99","repo":"microsoft/semantic-kernel","slug":"type-steptype-fullname-must-be-a-subclass-of-k","errorCode":null,"errorMessage":"Type '{stepType.FullName}' must be a subclass of KernelProcessStep.","messagePattern":"Type '(.+?)' must be a subclass of KernelProcessStep\\.","errorType":"validation","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"dotnet/src/Experimental/Process.Core/ProcessStepBuilder.cs","lineNumber":283,"sourceCode":"    /// </summary>\n    private object? _initialState;\n\n    private readonly Type _stepType;\n\n    /// <summary>\n    /// 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.\n    /// </summary>\n    /// <param name=\"stepType\">The <see cref=\"Type\"/> of the step.</param>\n    /// <param name=\"id\">The unique id of the step.</param>\n    /// <param name=\"processBuilder\">The process builder that this step is a part of.</param>\n    /// <param name=\"initialState\">Initial state of the step to be used on the step building stage</param>\n    internal ProcessStepBuilderTyped(Type stepType, string id, ProcessBuilder? processBuilder, object? initialState = default)\n        : base(id, processBuilder)\n    {\n        Verify.NotNull(stepType);\n        if (!typeof(KernelProcessStep).IsAssignableFrom(stepType))\n        {\n            throw new ArgumentException($\"Type '{stepType.FullName}' must be a subclass of KernelProcessStep.\", nameof(stepType));\n        }\n\n        this._stepType = stepType;\n        this.FunctionsDict = this.GetFunctionMetadataMap();\n        this._initialState = initialState;\n    }\n\n    /// <summary>\n    /// Builds the step with a state if provided\n    /// </summary>\n    /// <returns>An instance of <see cref=\"KernelProcessStepInfo\"/></returns>\n    internal override KernelProcessStepInfo BuildStep(ProcessBuilder processBuilder, KernelProcessStepStateMetadata? stateMetadata = null)\n    {\n        KernelProcessStepState? stateObject = null;\n        KernelProcessStepMetadataAttribute stepMetadataAttributes = KernelProcessStepMetadataFactory.ExtractProcessStepMetadataFromType(this._stepType);\n\n        if (this._stepType.TryGetSubtypeOfStatefulStep(out Type? genericStepType) && genericStepType is not null)\n        {","sourceCodeStart":265,"sourceCodeEnd":301,"githubUrl":"https://github.com/microsoft/semantic-kernel/blob/c028a0c7dc4f0814cdcbaba9d998f187a41197bf/dotnet/src/Experimental/Process.Core/ProcessStepBuilder.cs#L265-L301","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\npublic class MyWorker // does not inherit KernelProcessStep\n{\n    [KernelFunction]\n    public void DoWork() { }\n}\nprocess.AddStepFromType(typeof(MyWorker)); // throws\n\n// after\npublic class MyWorker : KernelProcessStep\n{\n    [KernelFunction]\n    public void DoWork() { }\n}\nprocess.AddStepFromType<MyWorker>();","handlingStrategy":"type-guard","validationCode":"if (!typeof(KernelProcessStep).IsAssignableFrom(stepType))\n    throw new ArgumentException(\n        $\"Type '{stepType.FullName}' must inherit from KernelProcessStep.\", nameof(stepType));\n\nprocess.AddStepFromType(stepType);","typeGuard":"bool IsValidStepType(Type stepType) => typeof(KernelProcessStep).IsAssignableFrom(stepType);","tryCatchPattern":null,"preventionTips":["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>."],"tags":["step-builder","type-validation","inheritance","kernel-process-step","dotnet"],"backgroundTag":null,"analyzedSha":"c028a0c7dc4f0814cdcbaba9d998f187a41197bf","analyzedAt":"2026-08-13T13:48:05.040Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}