Skip to content

GH-5439 Surface the real reason a job execution cannot be restarted#5440

Open
kyungrae wants to merge 1 commit into
spring-projects:mainfrom
kyungrae:fix/jobrestart-unknown-status-message
Open

GH-5439 Surface the real reason a job execution cannot be restarted#5440
kyungrae wants to merge 1 commit into
spring-projects:mainfrom
kyungrae:fix/jobrestart-unknown-status-message

Conversation

@kyungrae

Copy link
Copy Markdown

Resolves #5439

Problem

SimpleJobOperator.restart(JobExecution) wraps every exception thrown by run(...) into a JobRestartException with a hardcoded "job execution already running" message:

try {
    return run(job, parameters);
}
catch (Exception e) {
    throw new JobRestartException(
        String.format(ILLEGAL_STATE_MSG, "job execution already running", jobName, parameters), e);
}

The launcher (TaskExecutorJobLauncher.createJobExecution) already throws accurate, specific exceptions for the various non-restartable conditions. For example, when the last execution (or one of its step executions) ended in UNKNOWN status:

Cannot restart job from UNKNOWN status. The last execution ended with a failure that could not be rolled back, so it may be dangerous to proceed. Manual intervention is probably necessary.

Because the operator catches the broad Exception and rebuilds the message, that accurate reason is demoted to the cause and the top-level message wrongly states the job is "already running" — even though it is not (it is UNKNOWN, already complete, or had invalid parameters). Users and logs are then sent down the wrong debugging path.

Note: although SimpleJobOperator is deprecated in favour of TaskExecutorJobOperator, the latter inherits this method via super.restart(...), so the active operator is affected.

Change

Replace the broad catch (Exception e) with per-type handling:

  • JobExecutionAlreadyRunningException → keep the "job execution already running" message(the only genuinely-running case);
  • JobInstanceAlreadyCompleteException / InvalidJobParametersException → wrap while preserving their own message;
  • JobRestartException → propagate unchanged so its specific reason (e.g. the UNKNOWN-status message above) survives.

@kyungrae kyungrae force-pushed the fix/jobrestart-unknown-status-message branch from f443523 to 1980878 Compare June 23, 2026 06:34
SimpleJobOperator.restart(JobExecution) caught every exception thrown by run(...) and rewrapped it into a JobRestartException with a hardcoded "job execution already running" message. This masked the actual reason reported by the launcher — most notably "Cannot restart job from UNKNOWN status" — sending users down the wrong debugging path.

Catch only JobExecutionAlreadyRunningException for the "already running" message, wrap JobInstanceAlreadyCompleteException and InvalidJobParametersException with their own messages, and let JobRestartException propagate unchanged so its specific message survives.

Resolves spring-projects#5439

Signed-off-by: Kyungrae Kim <rlarudfo93@gmail.com>
@kyungrae kyungrae force-pushed the fix/jobrestart-unknown-status-message branch from 1980878 to 102617d Compare June 23, 2026 06:40
@kyungrae kyungrae changed the title Surface the real reason a job execution cannot be restarted GH-5439 Surface the real reason a job execution cannot be restarted Jun 23, 2026
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.

SimpleJobOperator.restart(JobExecution) masks the real failure reason with a misleading "job execution already running" message

1 participant