microsoft/semantic-kernel · critical · KernelException

Internal Process Error: The target event id must be specifie

Error message

Internal Process Error: The target event id must be specified when sending a message to a step.

What it means

ProcessActor.HandleMessageAsync is invoked only when this process runs as a step inside a parent process. It requires the incoming ProcessMessage.TargetEventId to be non-empty because that value is used to look up output edges and create the nested KernelProcessEvent that starts the sub-process. A null or whitespace TargetEventId means the routing infrastructure failed to identify the sub-process entry point.

Source

Thrown at dotnet/src/Experimental/Process.Runtime.Dapr/Actors/ProcessActor.cs:201

    /// <summary>
    /// The name of the step.
    /// </summary>
    protected override string Name => this._process?.State.Name ?? throw new KernelException("The Process must be initialized before accessing the Name property.").Log(this._logger);

    #endregion

    /// <summary>
    /// Handles a <see cref="ProcessMessage"/> that has been sent to the process. This happens only in the case
    /// of a process (this one) running as a step within another process (this one's parent). In this case the
    /// entire sub-process should be executed within a single superstep.
    /// </summary>
    /// <param name="message">The message to process.</param>
    internal override async Task HandleMessageAsync(ProcessMessage message)
    {
        if (string.IsNullOrWhiteSpace(message.TargetEventId))
        {
            throw new KernelException("Internal Process Error: The target event id must be specified when sending a message to a step.").Log(this._logger);
        }

        string eventId = message.TargetEventId!;
        if (this._outputEdges!.TryGetValue(eventId, out List<KernelProcessEdge>? edges) && edges is not null)
        {
            foreach (var edge in edges)
            {
                // Create the external event that will be used to start the nested process. Since this event came
                // from outside this processes, we set the visibility to internal so that it's not emitted back out again.
                KernelProcessEvent nestedEvent = new() { Id = eventId, Data = message.TargetEventData };

                // Run the nested process completely within a single superstep.
                await this.RunOnceAsync(nestedEvent.ToJson()).ConfigureAwait(false);
            }
        }
    }

    internal static ActorId GetScopedGlobalErrorEventBufferId(string processId) => new($"{ProcessConstants.GlobalErrorEventId}_{processId}");

View on GitHub (pinned to c028a0c7dc)

Solutions

  1. When embedding a sub-process in a parent, configure the edge targeting the sub-process using ProcessBuilder.WhereInputEventIs(eventId) so that the generated KernelProcessFunctionTarget carries a non-null TargetEventId.
  2. If constructing ProcessMessage objects manually (e.g. in a custom step or test), ensure TargetEventId is set to the sub-process entry event id.
  3. Audit the process graph edges to confirm that every edge targeting a DaprProcessInfo node has an associated TargetEventId in its function target.

Example fix

// before — edge to sub-process without input event id
builder.OnEvent(EventId).SendInputToProcess(subProcess);

// after — specify the input event id
builder.OnEvent(EventId).SendInputToProcess(subProcess.WhereInputEventIs(StartEventId));
Defensive patterns

Strategy: validation

Validate before calling

// When building a process graph with a sub-process step, always specify the input event:
builder.OnEvent(SomeEvent)
    .SendInputToProcess(subProcessBuilder.WhereInputEventIs(SubProcessStartEvent));

// This ensures KernelProcessFunctionTarget.TargetEventId is non-null for edges targeting sub-processes.

Try / catch

try
{
    await processStep.HandleMessageAsync(message);
}
catch (KernelException ex) when (ex.Message.Contains("target event id must be specified"))
{
    logger.LogError("Message routed to sub-process without TargetEventId. Check edge configuration.");
}

Prevention

When it happens

Trigger: A ProcessMessage arrives at a ProcessActor (acting as a nested step) whose TargetEventId was never set. This happens when ProcessMessageFactory.CreateFromEdge processes an edge whose KernelProcessFunctionTarget.TargetEventId is null (ordinary step-to-step edge misrouted to a sub-process) or when the message was constructed manually without setting TargetEventId.

Common situations: A process is embedded as a step in a parent process but its input edge was not configured via WhereInputEventIs(eventId) on the ProcessBuilder, so the TargetEventId defaults to null. Also occurs with custom or manually-constructed ProcessMessage objects that omit the field.

Related errors


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