microsoft/semantic-kernel · error · KernelException

The ActivateAsync method failed to complete.

Error message

The ActivateAsync method failed to complete.

What it means

Thrown by LocalStep.InitializeStepAsync when the reflection-invoked ActivateAsync method returns null instead of a ValueTask. After locating the method via GetMethod, the code invokes it and casts the result to ValueTask?; a null result means the method's actual return type is not ValueTask (e.g., it returns void, Task, or null).

Solutions

  1. Ensure ActivateAsync returns ValueTask, matching the KernelProcessStep contract.
  2. If overriding in a generic step, use 'public override ValueTask ActivateAsync(TState state)'.
  3. Avoid declaring ActivateAsync with a non-ValueTask return type.

Example fix

// before - returns Task
class MyStep : KernelProcessStep<MyState> {
    public override Task ActivateAsync(MyState state) { ... }
}
// after - returns ValueTask
class MyStep : KernelProcessStep<MyState> {
    public override ValueTask ActivateAsync(MyState state) { ... }
}
Defensive patterns

Strategy: type-guard

Type guard

// Verify ActivateAsync returns ValueTask
var stateType = typeof(MyStep).ExtractStateType(out _, logger);
var method = typeof(MyStep).GetMethod(nameof(KernelProcessStep.ActivateAsync), [stateType]);
if (method?.ReturnType != typeof(ValueTask)) { /* return type mismatch */ }

Prevention

When it happens

Trigger: The step type declares an ActivateAsync method with the right parameter type but a different return type than ValueTask, so the cast to ValueTask? produces null and the null-coalescing throw fires.

Common situations: A custom step where ActivateAsync returns Task or void instead of ValueTask; the method is a 'new' slot or hides the base method; signature drift between the declared override and what reflection binds to.

Related errors


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

Appendix: source

Thrown at dotnet/src/Experimental/Process.LocalRuntime/LocalStep.cs:318

        // Activate the step with user-defined state if needed
        Type stateType = this._stepInfo.InnerStepType.ExtractStateType(out Type? userStateType, this._logger);
        KernelProcessStepState stateObject = this._stepInfo.State;
        stateObject.InitializeUserState(stateType, userStateType);

        if (stateObject is null)
        {
            throw new KernelException("The state object for the KernelProcessStep could not be created.").Log(this._logger);
        }

        MethodInfo methodInfo =
            this._stepInfo.InnerStepType.GetMethod(nameof(KernelProcessStep.ActivateAsync), [stateType]) ??
            throw new KernelException("The ActivateAsync method for the KernelProcessStep could not be found.").Log(this._logger);

        this._stepState = stateObject;

        ValueTask activateTask =
            (ValueTask?)methodInfo.Invoke(this._stepInstance, [stateObject]) ??
            throw new KernelException("The ActivateAsync method failed to complete.").Log(this._logger);

        await this._stepInstance.ActivateAsync(stateObject).ConfigureAwait(false);
        await activateTask.ConfigureAwait(false);
    }

    /// <summary>
    /// Deinitializes the step
    /// </summary>
    public virtual Task DeinitializeStepAsync()
    {
        this._logger.LogInformation("Step {Name} has deinitialized", this.Name);
        return Task.CompletedTask;
    }

    /// <summary>
    /// Invokes the provides function with the provided kernel and arguments.
    /// </summary>
    /// <param name="function">The function to invoke.</param>

View on GitHub (pinned to c028a0c7dc)