Skip to content

[copilot-finds] Bug: Orchestration executor missing EVENTSENT handler causes duplicate sendEvent actions on replay #241

@github-actions

Description

@github-actions

Problem

The orchestration executor's processEvent switch statement in packages/durabletask-js/src/worker/orchestration-executor.ts (line ~131) is missing a case for pb.HistoryEvent.EventtypeCase.EVENTSENT (enum value 16). When an orchestrator calls ctx.sendEvent(), the sidecar records an EventSentEvent history event to confirm the action was processed. On the next replay, this event falls through to the default case and is logged as an unknown event type.

Without a handler, the sendEvent action remains in _pendingActions and is returned to the sidecar again via getActions(), potentially causing duplicate event delivery to the target orchestration instance.

Root Cause

All other "confirmation" events have dedicated handlers that remove actions from _pendingActions:

  • TASKSCHEDULEDhandleTaskScheduled removes the ScheduleTask action
  • TIMERCREATEDhandleTimerCreated removes the CreateTimer action
  • SUBORCHESTRATIONINSTANCECREATEDhandleSubOrchestrationCreated removes the action
  • ENTITYOPERATIONCALLED/ENTITYOPERATIONSIGNALEDvalidateEntityAction removes the action

EVENTSENT (enum 16) was missed from this pattern.

Note: This is analogous to issue #235 (ENTITYUNLOCKSENT) but for a different event type.

Proposed Fix

Add a handleEventSent case to the switch statement that:

  1. Retrieves the action from _pendingActions by event ID
  2. Deletes it from _pendingActions
  3. Validates it is a sendEvent action (throws NonDeterminismError otherwise)

Impact

Severity: Medium — On replay, orchestrations that call ctx.sendEvent() could cause the target instance to receive duplicate events. This affects any orchestration using fire-and-forget event delivery patterns.

Scenarios affected: Any orchestration that calls ctx.sendEvent() and subsequently gets replayed (e.g., after yielding a timer or activity after the sendEvent call).

Metadata

Metadata

Assignees

No one assigned

    Labels

    copilot-findsFindings from daily automated code review agent

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions