Skip to content

Report non-retryable PayloadValidationError as BAD_REQUEST - #1756

Open
bergundy wants to merge 2 commits into
temporalio:mainfrom
bergundy:nexus-payload-validation-bad-request
Open

Report non-retryable PayloadValidationError as BAD_REQUEST#1756
bergundy wants to merge 2 commits into
temporalio:mainfrom
bergundy:nexus-payload-validation-bad-request

Conversation

@bergundy

Copy link
Copy Markdown
Member

What changed

A payload codec or payload converter can now signal that a Nexus operation's input is invalid by raising a non-retryable ApplicationError of type PayloadValidationError while decoding the input. Such an error is translated into a BAD_REQUEST nexusrpc.HandlerError with the message Invalid operation input, retaining the original error as its __cause__.

Previously such an error became an INTERNAL handler error on the codec path, which callers retry — so a caller sending invalid input was retried until timeout instead of failing fast. On the converter path the type was already BAD_REQUEST, but the message was indistinguishable from a genuine decode failure; it now gets its own message.

Unchanged

  • ApplicationError of any other type → INTERNAL on the codec path (as before)
  • A retryable PayloadValidationErrorINTERNAL (non-retryable is required)
  • The external-storage retrieve path and the generic decode-failure messages are untouched
  • The serialize/output path is untouched — BAD_REQUEST would be wrong for a result-encoding failure

Tests

tests/nexus/test_workflow_caller_errors.py covers both the codec and converter stages: positive unit cases asserting BAD_REQUEST, not retryable, the wrapper message and the preserved cause; negative cases for a different error type and for a retryable PayloadValidationError; plus an end-to-end test asserting the caller sees a non-retryable BAD_REQUEST with an ApplicationError cause.

Cross-SDK

Part of a coordinated change; equivalent PRs exist for Go, Java, TypeScript and .NET. The wrapper message wording is aligned across SDKs, adapted to each SDK's message style.

A payload codec or payload converter can signal that a Nexus operation's input
is invalid by raising a non-retryable ApplicationError of type
PayloadValidationError while decoding the input. Such an error is now translated
into a BAD_REQUEST HandlerError retaining the original error as its cause,
instead of the INTERNAL handler error any other application error produces.

Application errors of any other type, and retryable PayloadValidationError
errors, keep their existing behavior.
@bergundy
bergundy requested a review from a team as a code owner August 14, 2026 22:50
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.

1 participant