microsoft/semantic-kernel · error · KernelException
The initial state provided for step {this.Name} is not of th
Error message
The initial state provided for step {this.Name} is not of the correct type. The expected type is {userStateType.Name}. What it means
Thrown by ProcessStepBuilder.BuildStep during JSON deserialization of a stateful step's initial state. The step derives from KernelProcessStep<TState>, and the state metadata supplied at build time is a JsonElement that cannot be deserialized into the user-defined state type TState. The framework catches the inner JsonException and rethrows this KernelException to surface a clear, type-named failure.
Source
Thrown at dotnet/src/Experimental/Process.Core/ProcessStepBuilder.cs:318
if (this._stepType.TryGetSubtypeOfStatefulStep(out Type? genericStepType) && genericStepType is not null)
{
// The step is a subclass of KernelProcessStep<>, so we need to extract the generic type argument
// and create an instance of the corresponding KernelProcessStepState<>.
var userStateType = genericStepType.GetGenericArguments()[0];
Verify.NotNull(userStateType);
var stateType = typeof(KernelProcessStepState<>).MakeGenericType(userStateType);
Verify.NotNull(stateType);
if (stateMetadata != null && stateMetadata.State != null && stateMetadata.State is JsonElement jsonState)
{
try
{
this._initialState = jsonState.Deserialize(userStateType);
}
catch (JsonException)
{
throw new KernelException($"The initial state provided for step {this.Name} is not of the correct type. The expected type is {userStateType.Name}.");
}
}
// If the step has a user-defined state then we need to validate that the initial state is of the correct type.
if (this._initialState is not null && this._initialState.GetType() != userStateType)
{
throw new KernelException($"The initial state provided for step {this.Name} is not of the correct type. The expected type is {userStateType.Name}.");
}
var initialState = this._initialState ?? Activator.CreateInstance(userStateType);
stateObject = (KernelProcessStepState?)Activator.CreateInstance(stateType, this.Name, stepMetadataAttributes.Version, this.Id);
stateType.GetProperty(nameof(KernelProcessStepState<object>.State))?.SetValue(stateObject, initialState);
}
else
{
// The step is a KernelProcessStep with no user-defined state, so we can use the base KernelProcessStepState.
stateObject = new KernelProcessStepState(this.Name, stepMetadataAttributes.Version, this.Id);
}View on GitHub (pinned to c028a0c7dc)
Solutions
- Inspect the expected type named in the message and reconcile your state JSON so every property matches the TState POCO (names, types, nullability).
- Deserialize the same JsonElement with JsonSerializer.Deserialize<TState>(jsonState) in a scratch test to capture the real JsonException with line/byte/path detail.
- Ensure the JsonSerializerOptions used to produce the JsonElement (e.g. property naming policy, case sensitivity) match what TState expects.
- If the state legitimately belongs to a different step, route it to the correct step or update the step's generic state argument.
Example fix
// before: state JSON has { "count": 5 } but TState expects an int named "Counter"
stepBuilder.BuildStep(pb, stateMetadata);
// after: align JSON property name to TState
// { "Counter": 5 }
stepBuilder.BuildStep(pb, stateMetadata); Defensive patterns
Strategy: validation
Validate before calling
// Validate the state JsonElement round-trips into TState before building
bool CanDeserializeState<TState>(JsonElement el, JsonSerializerOptions opt)
{
try { el.Deserialize<TState>(opt); return true; }
catch (JsonException) { return false; }
} Type guard
bool IsStateForStep<TState>(object state) => state is JsonElement el && CanDeserializeState<TState>(el, JsonSerializerOptions.Default);
Try / catch
try { builder.Build(); }
catch (KernelException ex) when (ex.Message.Contains("is not of the correct type"))
{
// log expectedType, re-serialize the supplied JsonElement for comparison
} Prevention
- Keep a single source of truth for TState schema and generate JSON from it.
- Add a unit test that round-trips each step's sample state JSON through Deserialize<TState>.
- Version state types and migrate serialized state when fields change.
When it happens
Trigger: Calling Build() on a ProcessBuilder whose stateful step was given KernelProcessStepStateMetadata with a State JsonElement whose shape does not match the declared user state type (missing properties, wrong property types, malformed JSON, or a state payload belonging to a different step type).
Common situations: Loading a process from serialized state where the schema evolved (renamed/removed TState fields), pasting state JSON from another step, or supplying a JsonElement produced by a different JsonSerializerOptions that yields incompatible tokens.
Related errors
- Unexpected author role: {role}
- Gemini API doesn't support author role: {value}
- Unsupported target type
- A target and Source must be specified before building the ed
- An output target has already been set.
AI-assisted analysis of microsoft/semantic-kernel@c028a0c7dc (2026-08-13).
Data as JSON: /api/errors/09e21cffeb750463.
Report an issue: GitHub.