microsoft/semantic-kernel · error · KernelException

A step cannot be activated before it has been initialized.

Error message

A step cannot be activated before it has been initialized.

What it means

ActivateStepAsync is the lazy one-time initialization that instantiates the step, loads kernel functions, and sets up input channels. It requires _stepInfo to be non-null, which is set by InitializeStep (called from InitializeStepAsync or OnActivateAsync). If ActivateStepAsync runs before initialization, this KernelException is thrown.

Source

Thrown at dotnet/src/Experimental/Process.Runtime.Dapr/Actors/StepActor.cs:355

        }
#pragma warning restore CA1031 // Do not catch general exception types
    }

    internal virtual Dictionary<string, Dictionary<string, object?>?> GenerateInitialInputs()
    {
        return this.FindInputChannels(this._functions, this._logger);
    }

    /// <summary>
    /// Initializes the step with the provided step information.
    /// </summary>
    /// <returns>A <see cref="ValueTask"/></returns>
    /// <exception cref="KernelException"></exception>
    protected virtual async ValueTask ActivateStepAsync()
    {
        if (this._stepInfo is null)
        {
            throw new KernelException("A step cannot be activated before it has been initialized.").Log(this._logger);
        }

        // Instantiate an instance of the inner step object
        KernelProcessStep stepInstance = (KernelProcessStep)ActivatorUtilities.CreateInstance(this._kernel.Services, this._innerStepType!);
        var kernelPlugin = KernelPluginFactory.CreateFromObject(stepInstance, pluginName: this._stepInfo.State.Name);

        // Load the kernel functions
        foreach (KernelFunction f in kernelPlugin)
        {
            this._functions.Add(f.Name, f);
        }

        // Initialize the input channels
        this._initialInputs = this.GenerateInitialInputs();
        this._inputs = this._initialInputs.ToDictionary(kvp => kvp.Key, kvp => kvp.Value?.ToDictionary(kvp => kvp.Key, kvp => kvp.Value));

        // Activate the step with user-defined state if needed
        KernelProcessStepState? stateObject = null;

View on GitHub (pinned to c028a0c7dc)

Solutions

  1. Call and await InitializeStepAsync before any method that triggers lazy activation (message processing, state extraction).
  2. Ensure that for re-activated actors, the Dapr state store contains ActorStateKeys.StepInfoState so OnActivateAsync can call InitializeStep.
  3. If the actor is fresh, always initialize first: InitializeStepAsync must be the first call after creating the proxy.

Example fix

// before
var stepProxy = factory.CreateActorProxy<IStep>(stepId, nameof(StepActor));
await stepProxy.ProcessIncomingMessagesAsync(); // triggers lazy activation, throws

// after
var stepProxy = factory.CreateActorProxy<IStep>(stepId, nameof(StepActor));
await stepProxy.InitializeStepAsync(stepInfo, parentProcessId);
await stepProxy.ProcessIncomingMessagesAsync();
Defensive patterns

Strategy: validation

Validate before calling

// Ensure InitializeStepAsync is called before any method that triggers lazy activation:
await stepActor.InitializeStepAsync(stepInfo, parentProcessId);
// Only then call methods that internally trigger _activateTask:
await stepActor.PrepareIncomingMessagesAsync();
await stepActor.ProcessIncomingMessagesAsync();
await stepActor.ToDaprStepInfoAsync();

Try / catch

try
{
    await stepActor.ToDaprStepInfoAsync();
}
catch (KernelException ex) when (ex.Message.Contains("cannot be activated before it has been initialized"))
{
    logger.LogError("Step actor activated before InitializeStepAsync. Call initialization first.");
}

Prevention

When it happens

Trigger: The lazy _activateTask fires (triggered by HandleMessageAsync, ToDaprStepInfoAsync, or PrepareIncomingMessagesAsync) before InitializeStepAsync has been called and before OnActivateAsync found persisted state. The _stepInfo field is still null.

Common situations: A step actor proxy is used without calling InitializeStepAsync first. The actor is re-activated from scratch (no persisted state) and a method triggers lazy activation before initialization. A race between proxy creation and initialization.

Related errors


AI-assisted analysis of microsoft/semantic-kernel@c028a0c7dc (2026-08-13). Data as JSON: /api/errors/f3a0ce7ea9a44288. Report an issue: GitHub.