From 56e35d6ceb8977202864114d094170c5aa2cc9f8 Mon Sep 17 00:00:00 2001 From: Greg Travis Date: Tue, 9 Jun 2026 11:25:35 -0400 Subject: [PATCH 1/3] Fix incorrect outcome check for polling --- .../internal/client/implementation.rb | 2 +- .../test/worker_workflow_handler_test.rb | 34 +++++++++++++++++++ 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/temporalio/lib/temporalio/internal/client/implementation.rb b/temporalio/lib/temporalio/internal/client/implementation.rb index 8dbf47f9..569504d7 100644 --- a/temporalio/lib/temporalio/internal/client/implementation.rb +++ b/temporalio/lib/temporalio/internal/client/implementation.rb @@ -217,7 +217,7 @@ def start_update_with_start_workflow(input) end # If the user wants to wait until completed, we must poll until outcome if not already there - if input.wait_for_stage == Temporalio::Client::WorkflowUpdateWaitStage::COMPLETED && update_resp.outcome + if input.wait_for_stage == Temporalio::Client::WorkflowUpdateWaitStage::COMPLETED && !update_resp.outcome update_resp.outcome = @client._impl.poll_workflow_update( Temporalio::Client::Interceptor::PollWorkflowUpdateInput.new( workflow_id: start_options.id, diff --git a/temporalio/test/worker_workflow_handler_test.rb b/temporalio/test/worker_workflow_handler_test.rb index b07a1dff..634ac760 100644 --- a/temporalio/test/worker_workflow_handler_test.rb +++ b/temporalio/test/worker_workflow_handler_test.rb @@ -691,6 +691,16 @@ def fail raise Temporalio::Error::ApplicationError, 'Intentional failure' end + workflow_update + def rejected_by_validator(value) + raise "Update handler should not run when validator rejects (got #{value})" + end + + workflow_update_validator :rejected_by_validator + def validate_rejected_by_validator(value) + raise 'Validator rejection reason' if value.negative? + end + workflow_update def start_waiting Temporalio::Workflow.wait_condition { @finish_waiting } @@ -784,6 +794,30 @@ def test_update_with_start_update_failure end end + def test_update_with_start_validator_rejection + worker = Temporalio::Worker.new( + client: env.client, + task_queue: "tq-#{SecureRandom.uuid}", + workflows: [UpdateWithStartWorkflow] + ) + worker.run do + id = "wf-#{SecureRandom.uuid}" + start_workflow_operation = Temporalio::Client::WithStartWorkflowOperation.new( + UpdateWithStartWorkflow, 123, + id:, task_queue: worker.task_queue, id_conflict_policy: Temporalio::WorkflowIDConflictPolicy::FAIL + ) + err = assert_raises(Temporalio::Error::WorkflowUpdateFailedError) do + env.client.execute_update_with_start_workflow( + UpdateWithStartWorkflow.rejected_by_validator, -1, + start_workflow_operation: + ) + end + assert_instance_of Temporalio::Error::ApplicationError, err.cause + assert_equal 'Validator rejection reason', err.cause.message + assert_equal 123, start_workflow_operation.workflow_handle.query(UpdateWithStartWorkflow.counter) + end + end + def test_update_with_start_cancel # Run worker worker = Temporalio::Worker.new( From 63f73cdca2d5f26cdfd15960670ec56a67a7cd67 Mon Sep 17 00:00:00 2001 From: Greg Travis Date: Tue, 9 Jun 2026 13:22:41 -0400 Subject: [PATCH 2/3] changelog --- CHANGELOG.md | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0051119d..02eaddd1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -28,4 +28,14 @@ and `Client#count_activities` provide visibility-backed queries; and `Client#asy accepts a standalone-form `ActivityIDReference` (constructed via `ActivityIDReference.for_standalone`) for async completion. -See https://docs.temporal.io/standalone-activity for the cross-SDK feature overview. \ No newline at end of file +See https://docs.temporal.io/standalone-activity for the cross-SDK feature overview. + +### Fixed + +#### `execute_update_with_start_workflow` no longer raises `RPCError NOT_FOUND` on validator rejection + +When a `workflow_update_validator` rejected an update sent via +`Client#execute_update_with_start_workflow` (or `#start_update_with_start_workflow` with +`wait_for_stage: COMPLETED`), the client polled history for an outcome that was never written +and surfaced the failure as `Temporalio::Error::RPCError` with code `NOT_FOUND`. The caller now +correctly receives `Temporalio::Error::WorkflowUpdateFailedError`. (#454) \ No newline at end of file From e7fdedd2813832354bbabeaabde92010a014892e Mon Sep 17 00:00:00 2001 From: Greg Travis Date: Tue, 9 Jun 2026 13:41:50 -0400 Subject: [PATCH 3/3] changelog blank line --- CHANGELOG.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index aaeca6d5..57b19d4b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -39,9 +39,10 @@ When a `workflow_update_validator` rejected an update sent via `wait_for_stage: COMPLETED`), the client polled history for an outcome that was never written and surfaced the failure as `Temporalio::Error::RPCError` with code `NOT_FOUND`. The caller now correctly receives `Temporalio::Error::WorkflowUpdateFailedError`. (#454) + #### Start Delay for Standalone Activities `Client#start_activity` and `Client#execute_activity` now accept a `start_delay:` kwarg. When set, the server creates the activity immediately, but defers dispatch to a worker until the delay elapses. Retry attempts do not re-apply the delay. `ScheduleToStart` and `ScheduleToClose` timeout clocks begin counting after the delay -elapses; `StartToClose` and `Heartbeat` are unaffected. Currently experimental. \ No newline at end of file +elapses; `StartToClose` and `Heartbeat` are unaffected. Currently experimental.