Skip to content

[copilot-finds] Bug: createTimer(seconds) uses Date.now() instead of currentUtcDateTime, violating orchestrator determinism #134

@github-actions

Description

@github-actions

Problem

RuntimeOrchestrationContext.createTimer() uses Date.now() when converting a relative seconds value to an absolute Date for the timer fire-at time:

// packages/durabletask-js/src/worker/runtime-orchestration-context.ts, line 297
if (!(fireAt instanceof Date)) {
  fireAt = new Date(Date.now() + fireAt * 1000);
}

Date.now() is explicitly listed as a non-deterministic call that must not be used in orchestrator code (see .github/copilot-instructions.md). The SDK provides context.currentUtcDateTime for this purpose, which returns the deterministic orchestration time set by OrchestratorStarted events.

Root Cause

The createTimer method was implemented with Date.now() as a convenience shorthand, but this violates the fundamental determinism rule that all orchestrator code must follow. During replay, Date.now() returns the current wall clock time (which could be minutes or hours after the original execution), producing a different timer fire-at value than the original execution.

While the replay mechanism currently tolerates this (the timer action is validated by ID and type only, not by fire-at time), it violates the SDK's documented contract and is inconsistent with how other Durable Task SDKs handle relative timer delays.

Proposed Fix

Replace Date.now() with this._currentUtcDatetime.getTime() so the timer fire-at is computed deterministically from the orchestration time.

Impact

Severity: Low-Medium. The timer fire-at is computed from a non-deterministic source, which is a determinism contract violation. In practice, the replay mechanism tolerates the different value because it only validates the action type and ID. However, this could become a breaking issue if the sidecar ever validates action content, and it is inconsistent with cross-SDK behavior.

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