Skip to content

Re-poll the update handle so long turns stop reporting failure - #211

Merged
imaustink merged 1 commit into
mainfrom
fix/temporal-engine-update-poll-window
Aug 18, 2026
Merged

Re-poll the update handle so long turns stop reporting failure#211
imaustink merged 1 commit into
mainfrom
fix/temporal-engine-update-poll-window

Conversation

@DavidNic11

Copy link
Copy Markdown
Collaborator

updateHandle.Get issues a long poll bounded by the SDK's own pollUpdateTimeout (60s in v1.46). When that window closes the gRPC call returns Canceled/DeadlineExceeded and the SDK surfaces WorkflowUpdateServiceTimeoutOrCanceledError WITHOUT retrying, even though the caller's context is still live.

That error is about the client call, not the update -- the SDK documents it as "not related to any general concept of timing out or cancelling a running update". The workflow keeps running and the result still arrives; only the poll gave up.

So any turn longer than the poll window reports failure while the work quietly succeeds. Observed with a bridged claude-code-swe-agent run: the UI showed

Timeout or cancellation waiting for update: stream terminated by
RST_STREAM with error code: CANCEL

while AgentRun reached Succeeded, BridgedAgentWorkflow reached Completed, and the agent had already pushed its work. Minutes-long runs are the norm for a coding agent, so this is the common case rather than an edge.

awaitTurnResult re-polls on that error and is used by both the streaming and non-streaming paths. The loop is bounded by ctx: the SDK returns the same error when the caller hangs up, so ctx.Err() is what separates "the window closed" from "nobody is listening", and prevents spinning.

/invoke is deliberately untouched -- it sets its own invokePollTimeout and reports "still running" by design.

updateHandle.Get issues a long poll bounded by the SDK's own
pollUpdateTimeout (60s in v1.46). When that window closes the gRPC call
returns Canceled/DeadlineExceeded and the SDK surfaces
WorkflowUpdateServiceTimeoutOrCanceledError WITHOUT retrying, even though
the caller's context is still live.

That error is about the client call, not the update -- the SDK documents
it as "not related to any general concept of timing out or cancelling a
running update". The workflow keeps running and the result still arrives;
only the poll gave up.

So any turn longer than the poll window reports failure while the work
quietly succeeds. Observed with a bridged claude-code-swe-agent run: the
UI showed

  Timeout or cancellation waiting for update: stream terminated by
  RST_STREAM with error code: CANCEL

while AgentRun reached Succeeded, BridgedAgentWorkflow reached Completed,
and the agent had already pushed its work. Minutes-long runs are the norm
for a coding agent, so this is the common case rather than an edge.

awaitTurnResult re-polls on that error and is used by both the streaming
and non-streaming paths. The loop is bounded by ctx: the SDK returns the
same error when the caller hangs up, so ctx.Err() is what separates "the
window closed" from "nobody is listening", and prevents spinning.

/invoke is deliberately untouched -- it sets its own invokePollTimeout and
reports "still running" by design.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

@imaustink imaustink left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚢

@imaustink
imaustink merged commit 6177a44 into main Aug 18, 2026
6 checks passed
@imaustink
imaustink deleted the fix/temporal-engine-update-poll-window branch August 18, 2026 13:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants