Skip to content

Add FirstExecutionRunID to start response#10873

Open
Quinn-With-Two-Ns wants to merge 5 commits into
temporalio:mainfrom
Quinn-With-Two-Ns:issue-8537
Open

Add FirstExecutionRunID to start response#10873
Quinn-With-Two-Ns wants to merge 5 commits into
temporalio:mainfrom
Quinn-With-Two-Ns:issue-8537

Conversation

@Quinn-With-Two-Ns

@Quinn-With-Two-Ns Quinn-With-Two-Ns commented Jun 29, 2026

Copy link
Copy Markdown
Contributor

What changed?

Add FirstExecutionRunID to start response

Why?

closes #8537

Today, when SDK gets StartWorkflowExecutionResponse with started as false or WorkflowExecutionAlreadyStartedFailure, it doesn't include the first execution run ID that we can bind successive calls to. It only provides the run ID. If you start a workflow today successfully, SDK uses the run ID as the first execution run ID on successive calls like cancel and signal and such. But if you start a workflow today w/ conflict policy of use existing and it doesn't start, that run ID is not acceptable for first execution run ID.

How did you test it?

  • built
  • run locally and tested manually
  • covered by existing tests
  • added new unit test(s)
  • added new functional test(s)

Note

Medium Risk
Touches workflow start, dedup, and ID-conflict paths plus a new persisted field and public API contract; behavior is heavily tested but mistakes could misreport chain identity to SDKs.

Overview
Exposes first_execution_run_id on StartWorkflowExecution and SignalWithStartWorkflowExecution responses (including dedup / use-existing paths) and on WorkflowExecutionAlreadyStarted failures, so clients can bind later calls to the head of a continue-as-new chain when started is false or the current run_id is not the chain root.

Persistence & mutable state: Adds WorkflowExecutionState.first_execution_run_id as the canonical store (the field on ExecutionInfo is deprecated), sets it from the started event, backfills from ExecutionInfo on load, and threads it through CurrentWorkflowConditionFailedError for conflict handling. When persisted state lacks the field, history loads mutable state and resolves via GetFirstRunID.

API bump: go.temporal.io/api is updated for the public response/error fields. Functional tests cover brand-new starts, dedup, FAIL policy, retry, reset, continue-as-new, and signal-with-start.

Reviewed by Cursor Bugbot for commit edfde7c. Bugbot is set up for automated code reviews on this repo. Configure here.

Comment thread service/history/workflow/mutable_state_impl.go

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 92186b1aa5

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread service/history/api/startworkflow/api.go
// FirstExecutionRunId was duplicated from ExecutionInfo onto ExecutionState so the dedup /
// conflict path can surface it without loading ExecutionInfo. Backfill in memory for records
// written before that change so the next persist writes it through.
if mutableState.executionState.FirstExecutionRunId == "" && mutableState.executionInfo.FirstExecutionRunId != "" {

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

We did something similar for StartTime when we moved that from ExecutionInfo to executionState

@yycptt yycptt left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

But if you start a workflow today w/ conflict policy of use existing and it doesn't start, that run ID is not acceptable for first execution run ID.

sorry I am bit confused here. Why is that runID not acceptable?

// Run ID of the first execution in the chain (set on WorkflowExecutionStarted). For workflows
// that have not been continued-as-new this equals run_id. Empty on records written before this
// field was added; consumers must not assume run_id in that case.
string first_execution_run_id = 8;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

We should also remove this field from WorkflowExecutionInfo, or we will storing an addition 32 bytes on every write op.

(partial write for ExecutionState itself could be a separate optimization foundations team can take I think)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

We can't remove it at least for one release no? Since we need to support rollback

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

yeah we can't in this release, just want to confirm we will do that eventually. Can you help mark the existing field as deprecated and comment on when we can stop writing to it? (guess the read part we need to keep forever...)

@bergundy bergundy left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Can you add functional test coverage for workflow retries, resets, and signals with start?

@Quinn-With-Two-Ns

Copy link
Copy Markdown
Contributor Author

Why is that runID not acceptable?

@yycptt because the run ID of the currently running workflow is not always the run ID of the first workflow in the chain, like if the workflow continued as new

Comment thread service/history/api/startworkflow/api.go
Comment thread tests/workflow_test.go
// TestStartWorkflowExecution_FirstExecutionRunId_AfterReset verifies that after a workflow is
// reset, a StartWorkflowExecution against the reset workflow (with FAIL or USE_EXISTING) reports
// the original run id as FirstExecutionRunId — not the reset's new run id.
func (s *WorkflowTestSuite) TestStartWorkflowExecution_FirstExecutionRunId_AfterReset() {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

There's actually a separate case here where we reset to a non-current run ID that can have a different first execution run ID. Worth the coverage IMHO.

@yycptt

yycptt commented Jun 30, 2026

Copy link
Copy Markdown
Member

Why is that runID not acceptable?

@yycptt because the run ID of the currently running workflow is not always the run ID of the first workflow in the chain, like if the workflow continued as new

oh I was thinking we can change the check in the api handler to see if the two firstExecutionRunID are the same.

But yeah as long as the existing field in the executionExecutionInfo will eventually be removed I don't have any concern.

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.

Fix All in Cursor

Reviewed by Cursor Bugbot for commit 4931879. Configure here.

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.

Add first execution run ID for already-started start workflow results

3 participants