Skip to content

Fix WorkflowReplayer for method-expression local activities - #2590

Open
chiliec wants to merge 1 commit into
temporalio:mainfrom
chiliec:fix/replay-method-local-activity
Open

Fix WorkflowReplayer for method-expression local activities#2590
chiliec wants to merge 1 commit into
temporalio:mainfrom
chiliec:fix/replay-method-local-activity

Conversation

@chiliec

@chiliec chiliec commented Aug 20, 2026

Copy link
Copy Markdown

What

Closes #2589.

WorkflowReplayer could not replay workflows that execute a local activity referenced by a method expression, e.g.

ExecuteLocalActivity(ctx, (*Activities).Foo)

Replaying such a workflow failed with:

expected 2 args for function: Foo but found 0

Root cause

In internal/workflow.go, ExecuteLocalActivity looks the activity up in the registry on replay. The string-name branch (localCtx.fn == nil) already has an IsReplayNamespace(...) fallback that substitutes a dummy function when the activity is unregistered, so replay works. The isMethod branch had no such fallback: on a registry miss it called validateFunctionArgs(localCtx.fn, args, ...) against the unbound method expression, which carries an extra receiver argument, and failed.

WorkflowReplayer only exposes RegisterWorkflow/RegisterDynamicWorkflow (activities can't be registered on it), so a method-expression local activity can never be made to hit the registry — the replay always failed.

Fix

Extend the existing IsReplayNamespace dummy-function fallback to the isMethod branch, mirroring the string-name branch exactly. One branch added in internal/workflow.go (+8 lines).

Tests

Added TestReplayWorkflowHistory_MethodLocalActivity in internal/internal_worker_test.go — a workflow that calls ExecuteLocalActivity(ctx, (*replayLocalActivities).ReplayLocalActivity) replayed through NewWorkflowReplayer, following the existing TestReplayWorkflowHistory_LocalActivity pattern.

Validation (real results, Go 1.25.4)

$ go test ./internal/ -run 'TestInternalWorkerTestSuite/TestReplayWorkflowHistory_MethodLocalActivity' -count=1
ok  	go.temporal.io/sdk/internal	0.059s

Verified genuine RED→GREEN — reverting only the internal/workflow.go fix (keeping the test) reproduces the exact reported error:

$ git stash push internal/workflow.go   # keep the test, drop the fix
$ go test ./internal/ -run '.../TestReplayWorkflowHistory_MethodLocalActivity' -count=1
ERROR activity failed with error. Error expected 2 args for function: ReplayLocalActivity but found 0
--- FAIL: TestInternalWorkerTestSuite/TestReplayWorkflowHistory_MethodLocalActivity
FAIL

Restoring the fix → green again. Full worker suite passes with no regressions:

$ go test ./internal/ -run 'TestInternalWorkerTestSuite' -count=1
ok  	go.temporal.io/sdk/internal	1.104s

go vet ./internal/ clean; both changed .go files are gofmt-clean (I intentionally did not reformat unrelated lines). Added a ### Fixed CHANGELOG.md entry to satisfy the changelog check.

First-time contributor here — happy to adjust the approach (the alternative discussed in the issue, adding RegisterActivity to WorkflowReplayer, is more involved and API-surface-changing; this mirrors the existing string-name fallback with minimal risk).

WorkflowReplayer could not replay workflows that execute a local activity
referenced by a method expression, e.g.
ExecuteLocalActivity(ctx, (*Activities).Foo). Such activities can never be
registered on the replayer (it only exposes RegisterWorkflow), so the
isMethod branch hit the registry miss and validated the unbound method
expression, which carries an extra receiver argument, failing with
"expected N args for function: Foo but found M".

The IsReplayNamespace fallback that already existed for string-named local
activities is now also applied to method-expression local activities, using
the same dummy replayer function.

Fixes temporalio#2589
@chiliec
chiliec requested a review from a team as a code owner August 20, 2026 00:09
@CLAassistant

CLAassistant commented Aug 20, 2026

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

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.

WorkflowReplayer cannot replay workflows using method-expression local activities

2 participants