{"record":{"id":"0f343ef6c1a56918","repo":"apache/dolphinscheduler","slug":"failed-to-cancel-emr-serverless-job-run","errorCode":null,"errorMessage":"Failed to cancel EMR Serverless job run","messagePattern":"Failed to cancel EMR Serverless job run","errorType":"exception","errorClass":"TaskException","httpStatus":null,"severity":"error","filePath":"dolphinscheduler-task-plugin/dolphinscheduler-task-emr-serverless/src/main/java/org/apache/dolphinscheduler/plugin/task/emrserverless/EmrServerlessTask.java","lineNumber":195,"sourceCode":"        }\n    }\n\n    @Override\n    public void cancelApplication() throws TaskException {\n        if (StringUtils.isEmpty(jobRunId)) {\n            log.warn(\"jobRunId is empty, skip cancel\");\n            return;\n        }\n        log.info(\"Cancelling EMR Serverless job run, applicationId: {}, jobRunId: {}\",\n                emrServerlessParameters.getApplicationId(), jobRunId);\n        try {\n            CancelJobRunRequest request = new CancelJobRunRequest()\n                    .withApplicationId(emrServerlessParameters.getApplicationId())\n                    .withJobRunId(jobRunId);\n            CancelJobRunResult result = emrServerlessClient.cancelJobRun(request);\n            log.info(\"Cancel job run result: {}\", result);\n        } catch (SdkBaseException e) {\n            throw new TaskException(\"Failed to cancel EMR Serverless job run\", e);\n        }\n    }\n\n    @Override\n    public List<String> getApplicationIds() throws TaskException {\n        return Collections.emptyList();\n    }\n\n    @Override\n    public AbstractParameters getParameters() {\n        return emrServerlessParameters;\n    }\n\n    /**\n     * Build StartJobRunRequest from parameters and user-provided JSON.\n     */\n    private StartJobRunRequest buildStartJobRunRequest() {\n        String startJobRunRequestJson;","sourceCodeStart":177,"sourceCodeEnd":213,"githubUrl":"https://github.com/apache/dolphinscheduler/blob/02eac45a1b6676e639fcbfb4be2243de5771b05d/dolphinscheduler-task-plugin/dolphinscheduler-task-emr-serverless/src/main/java/org/apache/dolphinscheduler/plugin/task/emrserverless/EmrServerlessTask.java#L177-L213","documentation":"cancelApplication calls CancelJobRun to stop a running EMR Serverless job run. Any AWS SDK SdkBaseException during that call is rethrown as TaskException with this message. Note EmrServerlessTaskException is not caught here, so API validation errors surface directly.","triggerScenarios":"emrServerlessClient.cancelJobRun(request) throws: job run already in a terminal state (ValidationException/ConflictException), wrong applicationId/jobRunId, network failure, or credentials lacking emr-serverless:CancelJobRun permission.","commonSituations":"Kill arrives after the job already finished (state SUCCESS/FAILED/CANCELLED -> AWS rejects cancel); IAM role missing CancelJobRun; stale jobRunId from a recovered failover; region mismatch between client config and the application.","solutions":["Check the 'caused by' AWS error: if the job run is already terminal, the cancel is unnecessary — treat as benign","Verify IAM permissions include emr-serverless:CancelJobRun","Confirm applicationId/jobRunId and region match the actual job run","If frequent, wrap the cancel so already-terminal-state errors are logged as warnings instead of failing the kill flow"],"exampleFix":"// before\ncatch (SdkBaseException e) {\n    throw new TaskException(\"Failed to cancel EMR Serverless job run\", e);\n}\n// after\ncatch (SdkBaseException e) {\n    if (String.valueOf(e).contains(\"InvalidRequestException\")) {\n        log.warn(\"Job run already in terminal state, skip cancel\", e);\n    } else {\n        throw new TaskException(\"Failed to cancel EMR Serverless job run\", e);\n    }\n}","handlingStrategy":"try-catch","validationCode":"// check job run state before cancel; terminal states reject CancelJobRun\nString state = emrServerlessClient.getJobRun(new GetJobRunRequest()\n    .withApplicationId(appId).withJobRunId(jobRunId)).getJobRun().getState();\nboolean cancelable = state.equals(\"SUBMITTED\") || state.equals(\"PENDING\")\n    || state.equals(\"SCHEDULED\") || state.equals(\"RUNNING\");","typeGuard":"boolean isTerminalJobRunState(String s) {\n    return s == null || java.util.Set.of(\"SUCCESS\",\"FAILED\",\"CANCELLED\",\"CANCEL_PENDING\").contains(s);\n}","tryCatchPattern":"try {\n    emrServerlessClient.cancelJobRun(request);\n} catch (SdkBaseException e) {\n    if (e instanceof AmazonServiceException\n            && ((AmazonServiceException) e).getErrorCode().contains(\"InvalidRequest\")) {\n        log.warn(\"Job run already terminal, cancel not needed\");\n    } else {\n        throw new TaskException(\"Failed to cancel EMR Serverless job run\", e);\n    }\n}","preventionTips":["Grant emr-serverless:CancelJobRun in the worker's IAM policy","Check job run state before cancelling to avoid expected terminal-state errors","Keep applicationId/jobRunId from the same submit; don't hand-edit appIds","Configure client region to match the application's region"],"tags":["aws","emr-serverless","cancel","sdk"],"backgroundTag":"api-request-failed","analyzedSha":"02eac45a1b6676e639fcbfb4be2243de5771b05d","analyzedAt":"2026-09-06T17:43:00.555Z","contentChangedAt":"2026-09-06T17:43:00.555Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}