apache/dolphinscheduler · error · EmrServerlessTaskException
Cannot parse StartJobRunRequest from JSON: ${startJobRunRequ
Error message
Cannot parse StartJobRunRequest from JSON: ${startJobRunRequestJson} What it means
After placeholder resolution, the JSON string is deserialized into the AWS StartJobRunRequest model with Jackson (UpperCamelCase naming, FAIL_ON_UNKNOWN_PROPERTIES disabled). A JsonProcessingException means the JSON is syntactically invalid or not shaped like StartJobRunRequest; the failing JSON text is embedded in the message.
Source
Thrown at dolphinscheduler-task-plugin/dolphinscheduler-task-emr-serverless/src/main/java/org/apache/dolphinscheduler/plugin/task/emrserverless/EmrServerlessTask.java:226
/**
* Build StartJobRunRequest from parameters and user-provided JSON.
*/
private StartJobRunRequest buildStartJobRunRequest() {
String startJobRunRequestJson;
try {
startJobRunRequestJson = ParameterUtils.convertParameterPlaceholders(
emrServerlessParameters.getStartJobRunRequestJson(),
ParameterUtils.convert(taskExecutionContext.getPrepareParamsMap()));
} catch (Exception e) {
throw new EmrServerlessTaskException("Failed to resolve parameter placeholders", e);
}
StartJobRunRequest request;
try {
request = objectMapper.readValue(startJobRunRequestJson, StartJobRunRequest.class);
} catch (JsonProcessingException e) {
throw new EmrServerlessTaskException(
"Cannot parse StartJobRunRequest from JSON: " + startJobRunRequestJson, e);
}
// Override applicationId and executionRoleArn from top-level parameters
request.setApplicationId(emrServerlessParameters.getApplicationId());
request.setExecutionRoleArn(emrServerlessParameters.getExecutionRoleArn());
// Set job name if provided
if (StringUtils.isNotEmpty(emrServerlessParameters.getJobName())) {
request.setName(emrServerlessParameters.getJobName());
} else {
request.setName(taskExecutionContext.getTaskName());
}
// Set client token for idempotency
request.setClientToken(taskExecutionContext.getTaskInstanceId() + "-" + System.currentTimeMillis());
return request;View on GitHub (pinned to 02eac45a1b)
Solutions
- Read the offending JSON printed in the message and validate it with a JSON linter
- Check the Jackson exception 'caused by' for line/column of the syntax error
- Use UpperCamelCase field names matching the AWS SDK StartJobRunRequest (releaseLabel, jobDriver, executionRoleArn...)
- Escape any quotes/newlines introduced by parameter substitution values
- Test with a minimal valid request (releaseLabel + jobDriver) and add fields incrementally
Example fix
// before
{"jobDriver":{"sparkSubmit":{"entryPoint":"s3://b/${param}"},}} // trailing comma
// after
{"jobDriver":{"sparkSubmitJobDriver":{"entryPoint":"s3://b/x.py","sparkSubmitParameters":"--conf spark.sql.x=y"}}} Defensive patterns
Strategy: validation
Validate before calling
// dry-run the deserialization locally with the plugin's exact mapper configuration
try {
new JsonMapper.builder()
.configure(FAIL_ON_UNKNOWN_PROPERTIES, false)
.propertyNamingStrategy(new PropertyNamingStrategies.UpperCamelCaseStrategy())
.build()
.readTree(startJobRunRequestJson); // throws on malformed JSON
} catch (JsonProcessingException e) {
throw new IllegalArgumentException("Invalid startJobRunRequestJson: " + e.getOriginalMessage());
} Try / catch
try {
request = objectMapper.readValue(startJobRunRequestJson, StartJobRunRequest.class);
} catch (JsonProcessingException e) {
log.error("JSON invalid at line {} col {}: {}",
e.getLocation().getLineNr(), e.getLocation().getColumnNr(), e.getOriginalMessage());
throw new TaskException("Fix startJobRunRequestJson", e);
} Prevention
- Validate the JSON with a linter before saving the task definition
- Use UpperCamelCase keys matching AWS SDK StartJobRunRequest fields
- Escape quotes/newlines in parameter values substituted into the JSON
- Build the request incrementally: minimal releaseLabel+jobDriver first, then add fields
When it happens
Trigger: objectMapper.readValue(startJobRunRequestJson, StartJobRunRequest.class) throws: malformed JSON (unquoted keys, trailing commas, single quotes), placeholder substitution produced invalid JSON, or keys don't map to StartJobRunRequest fields (e.g. lowercase 'jobDriver' field structure mismatch).
Common situations: Copy-pasted JSON with comments or trailing commas; nested quotes in sparkSubmitParameters broken escaping; substitution inserted unescaped quotes/newlines from a parameter value; using snake_case keys instead of UpperCamelCase required by this mapper.
Understand the failure class
Background: "failed to unmarshal" / json.Unmarshal errors: why parsing a response into a Go struct fails and how to fix it — this error's family across 23 libraries.
Related errors
- Parse json: <json> to class: <clazz> failed
- Object json deserialization exception.
- Object: + obj + to json serialization exception.
- String json deserialization exception.
- Json deserialization exception.
AI-assisted analysis of apache/dolphinscheduler@02eac45a1b (2026-09-06).
Data as JSON: /api/errors/52f14fd1aadbc986.
Report an issue: GitHub.