apache/flink · warning · JobStateUnknownException
Job %s is in state SUSPENDED
Error message
Job %s is in state SUSPENDED
What it means
Thrown as a JobStateUnknownException when requestJobStatus polls the REST /jobs/:jobid/status endpoint and the job is in JobStatus.SUSPENDED. A SUSPENDED job is one that was running but has been removed from the scheduler due to a failure (e.g., JobManager restart without recovery, or manual suspension). The client treats SUSPENDED as an unknown terminal state because the job is neither running nor cleanly finished.
Source
Thrown at flink-clients/src/main/java/org/apache/flink/client/program/rest/RestClusterClient.java:1005
return "Unknown address.";
}
}
// -------------------------------------------------------------------------
// RestClient Helper
// -------------------------------------------------------------------------
private CompletableFuture<JobStatus> requestJobStatus(JobID jobId) {
final JobStatusInfoHeaders jobStatusInfoHeaders = JobStatusInfoHeaders.getInstance();
final JobMessageParameters params = new JobMessageParameters();
params.jobPathParameter.resolve(jobId);
return sendRequest(jobStatusInfoHeaders, params)
.thenApply(JobStatusInfo::getJobStatus)
.thenApply(
jobStatus -> {
if (jobStatus == JobStatus.SUSPENDED) {
throw new JobStateUnknownException(
String.format("Job %s is in state SUSPENDED", jobId));
}
return jobStatus;
});
}
private static class JobStateUnknownException extends RuntimeException {
public JobStateUnknownException(String message) {
super(message);
}
}
private CompletableFuture<JobResult> requestJobResultInternal(@Nonnull JobID jobId) {
return pollResourceAsync(
() -> {
final JobMessageParameters messageParameters =
new JobMessageParameters();
messageParameters.jobPathParameter.resolve(jobId);View on GitHub (pinned to 2f3c205e92)
Solutions
- Check the JobManager logs for why the job entered SUSPENDED state (restart strategy exhausted, resource unavailable).
- If HA was not enabled, configure high-availability mode so the job can recover from JM failover.
- Increase the restart strategy limits (restart-strategy.fixed-delay.attempts) if the job failed due to transient errors.
- Restart the job from the latest savepoint or checkpoint.
Defensive patterns
Strategy: try-catch
Try / catch
try {
JobStatus status = client.getJobStatus(jobId).get();
} catch (ExecutionException e) {
Throwable cause = ExceptionUtils.stripExecutionException(e);
if (cause instanceof RestClusterClient.JobStateUnknownException) {
// job is SUSPENDED — may need to restart from savepoint
log.warn("Job {} is suspended, attempting recovery from savepoint", jobId);
}
} Prevention
- Enable HA mode so jobs survive JobManager failover.
- Configure an adequate restart strategy.
- Take periodic savepoints for recovery.
When it happens
Trigger: Polling job status via getJobStatus(jobId) when the job has been suspended — typically after a JobManager failover where the job could not be recovered, or when a job is manually suspended via the REST API.
Common situations: JobManager restarted from a checkpoint/savepoint but the job was not configured for HA recovery; job exceeded the restart strategy limit and was suspended; manual suspension via REST PATCH /jobs/:jobid; concurrent job cancellation from another client.
Related errors
- Failed to serialize ExecutionPlan.
- Failed to get the FileSystem of artifact {artifactFilePath}.
- Failed to submit ExecutionPlan.
- {checkpointInfo.getFailureCause()}
- Failed to deserialize coordination response
AI-assisted analysis of apache/flink@2f3c205e92 (2026-08-14).
Data as JSON: /api/errors/c37a7c3373a3fe36.
Report an issue: GitHub.