[Bug] REST API error response only contains top-level message, hiding root cause
Environment
- SeaTunnel Version: 2.3.13
- Deployment Mode: SeaTunnel Engine (Zeta) cluster
- REST API Endpoint:
POST /hazelcast/rest/maps/submit-job
Problem Description
When submitting a job via the REST API and the job fails during initialization, the returned JSON error response only contains the top-level exception message (e.g., Factory initialize failed). The actual root cause — which is usually nested inside the Caused by chain — is completely lost in the HTTP response.
This makes remote debugging extremely difficult because callers of the REST API have no idea what really went wrong (e.g., missing required options, SQL syntax errors, connection timeouts, permission issues).
Steps to Reproduce
- Start SeaTunnel cluster.
- Submit a deliberately broken job via REST API:
curl -X POST http://127.0.0.1:5802/hazelcast/rest/maps/submit-job \
-H "Content-Type: application/json" \
-d '{
"env": {"job.mode": "BATCH"},
"source": [{"FakeSource": {"row.num": 1}}],
"sink": [{"Doris": {"fenodes": "127.0.0.1:8030"}}]
}'
- Observe the HTTP response:
{
"status": "fail",
"message": "Factory initialize failed"
}
- Compare with the server log
logs/seatunnel-engine-server.log, which contains the full Caused by stack trace.
Root Cause Analysis
In seatunnel-starter.jar, the class org.apache.seatunnel.engine.server.rest.filter.ExceptionHandlingFilter handles exceptions thrown during REST request processing.
Currently, in the handleException method, it only calls:
errResponse.setMessage(exception.getMessage());
It does not recursively traverse Throwable.getCause(), so all nested exception information is discarded before being serialized back to the HTTP client.
Expected Behavior
The REST API should return the full error chain so that remote callers can understand the root cause without logging into the server.
Expected response example:
{
"status": "fail",
"message": "Factory initialize failed | Caused by: OptionValidationException: the options('database') are required."
}
Suggested Fix
Modify ExceptionHandlingFilter to build a full error message by recursively walking the exception chain:
private String buildFullErrorMessage(Throwable throwable) {
StringBuilder sb = new StringBuilder();
sb.append(throwable.getMessage());
Throwable cause = throwable.getCause();
while (cause != null) {
sb.append(" | Caused by: ")
.append(cause.getClass().getSimpleName())
.append(": ")
.append(cause.getMessage());
cause = cause.getCause();
}
return sb.toString().replace("\"", "'");
}
Then use buildFullErrorMessage(exception) instead of exception.getMessage() when constructing the error response.
Additional Context
- This issue affects all REST API clients that rely on the HTTP response for diagnostics.
- Server-side logs do contain the full stack trace, but in production environments, REST API users often do not have direct access to the server filesystem.
- I have verified that patching
ExceptionHandlingFilter.class in seatunnel-starter.jar with the above logic resolves the issue locally.
[Bug] REST API error response only contains top-level message, hiding root cause
Environment
POST /hazelcast/rest/maps/submit-jobProblem Description
When submitting a job via the REST API and the job fails during initialization, the returned JSON error response only contains the top-level exception message (e.g.,
Factory initialize failed). The actual root cause — which is usually nested inside theCaused bychain — is completely lost in the HTTP response.This makes remote debugging extremely difficult because callers of the REST API have no idea what really went wrong (e.g., missing required options, SQL syntax errors, connection timeouts, permission issues).
Steps to Reproduce
{ "status": "fail", "message": "Factory initialize failed" }logs/seatunnel-engine-server.log, which contains the fullCaused bystack trace.Root Cause Analysis
In
seatunnel-starter.jar, the classorg.apache.seatunnel.engine.server.rest.filter.ExceptionHandlingFilterhandles exceptions thrown during REST request processing.Currently, in the
handleExceptionmethod, it only calls:It does not recursively traverse
Throwable.getCause(), so all nested exception information is discarded before being serialized back to the HTTP client.Expected Behavior
The REST API should return the full error chain so that remote callers can understand the root cause without logging into the server.
Expected response example:
{ "status": "fail", "message": "Factory initialize failed | Caused by: OptionValidationException: the options('database') are required." }Suggested Fix
Modify
ExceptionHandlingFilterto build a full error message by recursively walking the exception chain:Then use
buildFullErrorMessage(exception)instead ofexception.getMessage()when constructing the error response.Additional Context
ExceptionHandlingFilter.classinseatunnel-starter.jarwith the above logic resolves the issue locally.