You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Validate the retry delay is a valid proto duration.
Why?
Prevent malformed retry delays from poisoning Nexus completions.
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)
Potential risks
Potentially users could have been sending an invalid proto duration, unclear how exactly, and now we would fail their request.
Note
Medium Risk
Request validation on the activity-failure path may reject clients that previously sent invalid duration payloads; behavior change is intentional but could surface latent bad callers.
Overview RespondActivityTaskFailed and RespondActivityTaskFailedById now reject failures whose ApplicationFailureInfo.NextRetryDelay is not a valid google.protobuf.Duration, including nested causes in the failure chain.
A new validateActivityFailureNextRetryDelays helper runs CheckValid() on any set delay and returns InvalidArgument with a clear message instead of accepting malformed values that could break downstream handling (e.g. Nexus completions).
Unit tests cover edge cases (range, sign mismatch, nested invalid delay); functional tests confirm both respond-by-token and respond-by-ID paths leave the activity RUNNING when validation fails and still allow a valid failure afterward.
Reviewed by Cursor Bugbot for commit b7bb95b. Bugbot is set up for automated code reviews on this repo. Configure here.
For the record the bug report from Codex is as follow
ApplicationFailureInfo.NextRetryDelay is a google.protobuf.Duration. Binary protobuf and gRPC can carry a structurally invalid duration, such as {seconds: 1, nanos: -1}, but protobuf JSON rejects it. RespondActivityTaskFailed validates the failure variant and byte size without validating this nested duration, and the standalone activity reads it with AsDuration without checking CheckValid. If the failure is terminal, the malformed duration remains in the persisted failure.
Nexus completion later converts the entire Temporal failure with protojson.Marshal. That conversion rejects the duration before either the internal or system callback invoker is constructed, so the target Nexus operation never receives the already-committed activity outcome. The callback task returns an internal processing error and remains scheduled for queue retries, or eventually reaches the DLQ when that policy is enabled; retrying cannot repair the persisted failure.
Unexpected task errors retry until the configured DLQ threshold, if any, without mutating the malformed activity outcome: service/history/queues/executable.go:613
Impact:
A buggy or malicious worker reports a terminal standalone activity failure with a small but invalid NextRetryDelay duration.
The frontend accepts the binary gRPC request, and History closes the activity with that failure.
The activity's Nexus callback cannot serialize its completion arguments, so no request reaches the target namespace.
The backing Nexus operation remains running until its own timeout, or indefinitely if it has none, while the source callback repeatedly fails or is sent to the DLQ.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What changed?
Validate the retry delay is a valid proto duration.
Why?
Prevent malformed retry delays from poisoning Nexus completions.
How did you test it?
Potential risks
Potentially users could have been sending an invalid proto duration, unclear how exactly, and now we would fail their request.
Note
Medium Risk
Request validation on the activity-failure path may reject clients that previously sent invalid duration payloads; behavior change is intentional but could surface latent bad callers.
Overview
RespondActivityTaskFailed and RespondActivityTaskFailedById now reject failures whose
ApplicationFailureInfo.NextRetryDelayis not a validgoogle.protobuf.Duration, including nested causes in the failure chain.A new
validateActivityFailureNextRetryDelayshelper runsCheckValid()on any set delay and returns InvalidArgument with a clear message instead of accepting malformed values that could break downstream handling (e.g. Nexus completions).Unit tests cover edge cases (range, sign mismatch, nested invalid delay); functional tests confirm both respond-by-token and respond-by-ID paths leave the activity RUNNING when validation fails and still allow a valid failure afterward.
Reviewed by Cursor Bugbot for commit b7bb95b. Bugbot is set up for automated code reviews on this repo. Configure here.