microsoft/semantic-kernel · warning · KernelException
External message channel not configured for step
Error message
External message channel not configured for step
What it means
Thrown by KernelProcessStepExternalContext.CloseExternalEventChannelAsync when the internal _externalMessageChannel field is null. This mirrors the EmitExternalEventAsync guard: the context was created without an IExternalKernelProcessMessageChannel, so there is nothing to uninitialize/close.
Source
Thrown at dotnet/src/Experimental/Process.Abstractions/KernelProcessStepExternalContext.cs:49
{
if (this._externalMessageChannel == null)
{
throw new KernelException($"External message channel not configured for step with topic {processEventData.ExternalTopicName}");
}
await this._externalMessageChannel.EmitExternalEventAsync(processEventData.ExternalTopicName, processEventData).ConfigureAwait(false);
}
/// <summary>
/// Closes connection with external messaging channel
/// </summary>
/// <returns><see cref="Task"/></returns>
/// <exception cref="KernelException"></exception>
public async Task CloseExternalEventChannelAsync()
{
if (this._externalMessageChannel == null)
{
throw new KernelException("External message channel not configured for step");
}
await this._externalMessageChannel.Uninitialize().ConfigureAwait(false);
}
}
View on GitHub (pinned to c028a0c7dc)
Solutions
- Guard the close call: check whether the external context has a channel before calling CloseExternalEventChannelAsync, or catch KernelException during teardown.
- Ensure the same IExternalKernelProcessMessageChannel is consistently injected into all step contexts for the lifetime of the process.
- If using a custom process host, verify that it constructs KernelProcessStepExternalContext with the channel instance for every proxy-enabled step.
Example fix
// before
await context.CloseExternalEventChannelAsync(); // throws if no channel
// after
try
{
await context.CloseExternalEventChannelAsync();
}
catch (KernelException)
{
// No external channel was configured; safe to ignore during teardown.
} Defensive patterns
Strategy: try-catch
Try / catch
try
{
await context.CloseExternalEventChannelAsync();
}
catch (KernelException ex) when (ex.Message.Contains("External message channel not configured"))
{
// Safe to ignore during teardown if no channel was configured.
} Prevention
- Only call CloseExternalEventChannelAsync on contexts known to have a channel.
- Centralize teardown logic to skip contexts without external channels.
- Track which step contexts received channels in your process host.
When it happens
Trigger: CloseExternalEventChannelAsync is called on a KernelProcessStepExternalContext that was constructed without an external channel (the default constructor or one called with null). This typically happens during process teardown or step disposal when the external channel was never set up.
Common situations: Process shutdown logic that unconditionally calls CloseExternalEventChannelAsync on every step context regardless of whether a channel exists. Test harnesses that create step contexts without full runtime wiring. Mismatched setup where Emit succeeded on some paths but the channel was disposed or not injected on others.
Related errors
- External message channel not configured for step with topic
- No IExternalKernelProcessMessageChannel found, need at least
- Configuration not found, please setup the notebooks first us
- AZURE_OPENAI_ENDPOINT is not set.
- AZURE_OPENAI_ENDPOINT is not set.
AI-assisted analysis of microsoft/semantic-kernel@c028a0c7dc (2026-08-13).
Data as JSON: /api/errors/3fdb3d3e139aeb56.
Report an issue: GitHub.