Skip to content

fix(sdk): don't NPE in CallbackFailedException when the callback has no error - #774

Merged
zhongkechen merged 2 commits into
aws:mainfrom
Pitchfork-and-Torch:fix/callback-failed-null-error
Oct 5, 2026
Merged

zhongkechen merged 2 commits into
aws:mainfrom
Pitchfork-and-Torch:fix/callback-failed-null-error

Conversation

@Pitchfork-and-Torch

Copy link
Copy Markdown
Contributor

By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.

Issue Link, if available

Fixes #773

Description

SendDurableExecutionCallbackFailure accepts a request with no Error, so a CALLBACK operation can come back FAILED with no CallbackDetails.Error. CallbackFailedException.buildMessage called error.errorType() without a null check. CallbackOperation.get() (and ChildContextOperation.handleWaitForCallbackFailure) then threw NullPointerException instead of CallbackFailedException, and a catch (CallbackFailedException e) block never saw it.

The fix is a null guard in buildMessage that falls back to "Callback failed", the same message the JS SDK uses. getErrorObject() stays null, which DurableOperationException already allows. Both call sites build the exception through this constructor, so they are both covered.

Demo/Screenshots

N/A

Checklist

  • I have filled out every section of the PR template
  • I have thoroughly tested this change

Testing

Unit Tests

Yes. CallbackExceptionTest.testCallbackFailedExceptionWithoutError builds a callback operation with no error and checks the callback id, the operation, a null error object, and the message "Callback failed".

  • Before the fix: NullPointerException: Cannot invoke "ErrorObject.errorType()" because "error" is null at CallbackFailedException.buildMessage.
  • After the fix: mvn -pl sdk -am test passes, 1203 tests, 0 failures. mvn spotless:check is clean.

Integration Tests

No. This is an isolated fix inside the exception's constructor, and the unit test covers it.

Examples

N/A

…no error

SendDurableExecutionCallbackFailure accepts a request without an Error, so a
FAILED callback operation can arrive with no CallbackDetails.Error. buildMessage
dereferenced the error unconditionally, so get() threw NullPointerException
instead of CallbackFailedException. Fall back to "Callback failed", matching
the JS SDK.

Fixes aws#773
@Pitchfork-and-Torch
Pitchfork-and-Torch requested a review from a team October 5, 2026 16:59
@Pitchfork-and-Torch
Pitchfork-and-Torch deployed to ai-pr-review-runtime October 5, 2026 16:59 — with GitHub Actions Active

@zhongkechen zhongkechen left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Thanks for fixing this and adding a regression test! The null guard correctly handles a missing callback error while preserving the existing behavior when an error is present. I checked both callback failure paths and ran the 27 related exception, callback-operation, and child-context tests locally; all passed.

Parallel can finish after the second failure while a successful branch is still running. That branch may skip its terminal checkpoint, so a fixed total history size depends on scheduling.

Assert the failure threshold, branch outcomes, and the parallel operation's own checkpoint events instead. Verify that replay preserves both the result and history in FLAT and NESTED modes.

Validation: Java 25 SDK, testing utilities, and local integration suites (1647 tests); Java 17 parallel and child-context tests; Spotless check. A controlled late-branch probe also verified stable results and history on replay.
@zhongkechen
zhongkechen merged commit 9ab9f52 into aws:main Oct 5, 2026
18 of 20 checks passed
@zhongkechen zhongkechen mentioned this pull request Oct 8, 2026
3 of 7 tasks
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.

CallbackFailedException throws NullPointerException when a failed callback has no Error

2 participants