apache/seatunnel · error · IllegalArgumentException
The jobId must not be empty.
Error message
The jobId must not be empty.
What it means
CheckpointHistoryServlet.doGet reads the jobId from the request path info (form /jobId). If the path is missing, empty, or only a slash, it throws IllegalArgumentException because a numeric job id is mandatory to look up checkpoint history. Long.parseLong would otherwise fail on garbage, so the explicit check guards the empty case.
Source
Thrown at seatunnel-engine/seatunnel-engine-server/src/main/java/org/apache/seatunnel/engine/server/rest/servlet/CheckpointHistoryServlet.java:45
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class CheckpointHistoryServlet extends BaseServlet {
private final CheckpointMonitorRestService restService;
public CheckpointHistoryServlet(NodeEngineImpl nodeEngine) {
super(nodeEngine);
this.restService = new CheckpointMonitorRestService(nodeEngine);
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
String jobIdStr = req.getPathInfo();
if (jobIdStr == null || jobIdStr.length() <= 1) {
throw new IllegalArgumentException("The jobId must not be empty.");
}
long jobId = Long.parseLong(jobIdStr.substring(1));
Integer pipelineId =
req.getParameter("pipelineId") == null
? null
: Integer.parseInt(req.getParameter("pipelineId"));
int limit =
req.getParameter("limit") == null
? 20
: Integer.parseInt(req.getParameter("limit"));
CheckpointStatus status = null;
if (req.getParameter("status") != null) {
status = CheckpointStatus.valueOf(req.getParameter("status").toUpperCase());
}
writeJson(resp, restService.getHistory(jobId, pipelineId, limit, status));
}
}
View on GitHub (pinned to cf67b549a7)
Solutions
- Append the numeric job id to the URL path, e.g. GET /checkpoint-history/<jobId>
- Validate the jobId is present and numeric in the client before calling
- Ensure proxies/gateways do not strip the trailing path segment
- Catch IllegalArgumentException client-side and surface a 400 with a helpful message
Example fix
// before resp = get(base + "/checkpoint-history/"); // missing id // after resp = get(base + "/checkpoint-history/" + jobId); // jobId = 918273645
Defensive patterns
Strategy: validation
Validate before calling
if (jobId == null || jobId <= 0) throw new IllegalArgumentException("jobId required");
URL url = base + "/checkpoint-history/" + jobId; Type guard
boolean hasJobId(String pathInfo) { return pathInfo != null && pathInfo.length() > 1 && pathInfo.substring(1).matches("\\d+"); } Try / catch
try { resp = getHistory(jobId); } catch (IllegalArgumentException e) { show("Provide a numeric jobId in the path"); } Prevention
- Persist the jobId returned at submission time
- Build URLs from typed jobId fields, never string concatenation of nullable values
- Test endpoints with the no-id URL to confirm 400 responses
When it happens
Trigger: GET to the checkpoint-history endpoint without a trailing /<jobId> path segment, e.g. GET /checkpoint-history/ or /checkpoint-history.
Common situations: Client omits the job id when polling history after a job failed to submit; reverse-proxy rewrites drop the path suffix; users copy the endpoint URL without appending the id; bookmarking the base URL.
Understand the failure class
Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.
Related errors
- The jobId must not be empty.
- The jobId must not be empty.
- Parameter 'pluginName' cannot be empty.
- Page number must be greater than 0
- Page number exceeds total pages
AI-assisted analysis of apache/seatunnel@cf67b549a7 (2026-09-10).
Data as JSON: /api/errors/51893cf8ce8af9ce.
Report an issue: GitHub.