Skip to content

Fix NPE in TryExecutor when retry policy omits optional fields#1519

Open
mcruzdev wants to merge 2 commits into
serverlessworkflow:mainfrom
mcruzdev:issue-1517
Open

Fix NPE in TryExecutor when retry policy omits optional fields#1519
mcruzdev wants to merge 2 commits into
serverlessworkflow:mainfrom
mcruzdev:issue-1517

Conversation

@mcruzdev

@mcruzdev mcruzdev commented Jul 3, 2026

Copy link
Copy Markdown
Collaborator

The spec defines backoff, limit, and delay as optional in a retry policy, but the runtime assumed all three were always present, causing NullPointerException when any was omitted.

  • Default to constant backoff when backoff is not specified
  • Default to unlimited retries when limit is not specified
  • Default to zero delay when delay is not specified

Closes #1517

The spec defines backoff, limit, and delay as optional in a retry
policy, but the runtime assumed all three were always present,
causing NullPointerException when any was omitted.

- Default to constant backoff when backoff is not specified
- Default to unlimited retries when limit is not specified
- Default to zero delay when delay is not specified

Signed-off-by: Matheus Cruz <matheuscruz.dev@gmail.com>
Copilot AI review requested due to automatic review settings July 3, 2026 19:51
@mcruzdev mcruzdev requested a review from fjtirado as a code owner July 3, 2026 19:51

Copilot AI 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.

Pull request overview

This PR addresses runtime NullPointerException failures when a RetryPolicy omits optional fields (as allowed by the spec) by adding defaulting/guard logic in the retry executor path and adding regression tests for common omission scenarios.

Changes:

  • Default retry backoff to constant backoff when retryPolicy.backoff is omitted.
  • Default retry limit to a max when retryPolicy.limit / limit.attempt is omitted.
  • Default retry delay to Duration.ZERO when retryPolicy.delay is omitted.
  • Add fluent DSL tests covering retry behavior when backoff, limit, or delay are omitted.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.

File Description
impl/core/src/main/java/io/serverlessworkflow/impl/executors/TryExecutor.java Adds resolveMaxAttempts() and defaults missing backoff to constant backoff.
impl/core/src/main/java/io/serverlessworkflow/impl/executors/retry/AbstractRetryIntervalFunction.java Defaults missing delay to zero duration via a constant resolver.
experimental/test/src/test/java/io/serverlessworkflow/fluent/test/FuncTryCatchTest.java Adds regression tests for retry policies missing backoff, limit, or delay.
Comments suppressed due to low confidence (1)

impl/core/src/main/java/io/serverlessworkflow/impl/executors/retry/AbstractRetryIntervalFunction.java:42

  • The constructor still dereferences jitter.getFrom() / jitter.getTo() without guarding against them being null. The fluent builder allows setting only one of these, so this path can still throw a NullPointerException even with the top-level jitter != null check. Suggest treating missing from/to as no jitter (Duration.ZERO).
    if (jitter != null) {
      minJitteringResolver = Optional.of(WorkflowUtils.fromTimeoutAfter(appl, jitter.getFrom()));
      maxJitteringResolver = Optional.of(WorkflowUtils.fromTimeoutAfter(appl, jitter.getTo()));

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +118 to +127
private static int resolveMaxAttempts(RetryLimit limit) {
if (limit == null) {
return Integer.MAX_VALUE;
}
RetryLimitAttempt attempt = limit.getAttempt();
if (attempt == null) {
return Integer.MAX_VALUE;
}
return attempt.getCount();
}
The retry limit default was set to Integer.MAX_VALUE, but when no
limit is configured the retry should not execute. Also update the
test to verify the workflow fails when no retry limit is set.

Signed-off-by: Matheus Cruz <matheuscruz.dev@gmail.com>
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.

NPE in TryExecutor when retry is configured without explicit backoff strategy

2 participants