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

  1. Read the offending JSON printed in the message and validate it with a JSON linter
  2. Check the Jackson exception 'caused by' for line/column of the syntax error
  3. Use UpperCamelCase field names matching the AWS SDK StartJobRunRequest (releaseLabel, jobDriver, executionRoleArn...)
  4. Escape any quotes/newlines introduced by parameter substitution values
  5. 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

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


AI-assisted analysis of apache/dolphinscheduler@02eac45a1b (2026-09-06). Data as JSON: /api/errors/52f14fd1aadbc986. Report an issue: GitHub.