{"record":{"id":"3787af436639ed55","repo":"apache/seatunnel","slug":"restoresourcejobid-is-required-when-restoremode","errorCode":null,"errorMessage":"restoreSourceJobId is required when restoreMode=${restoreMode}","messagePattern":"restoreSourceJobId is required when restoreMode=(.+?)","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":400,"severity":"error","filePath":"seatunnel-engine/seatunnel-engine-server/src/main/java/org/apache/seatunnel/engine/server/rest/service/BaseService.java","lineNumber":1341,"sourceCode":"        JobConfig jobConfig = new JobConfig();\n        jobConfig.setName(\n                StringUtils.isEmpty(requestParams.get(RestConstant.JOB_NAME))\n                        ? jobName\n                        : requestParams.get(RestConstant.JOB_NAME));\n\n        RestoreMode restoreMode = resolveRestoreMode(requestParams);\n        String jobIdStr = requestParams.get(RestConstant.JOB_ID);\n        Long finalJobId = StringUtils.isNotBlank(jobIdStr) ? Long.parseLong(jobIdStr) : null;\n        Long restoreSourceJobId =\n                StringUtils.isNotBlank(requestParams.get(RestConstant.RESTORE_SOURCE_JOB_ID))\n                        ? Long.parseLong(requestParams.get(RestConstant.RESTORE_SOURCE_JOB_ID))\n                        : null;\n        // Keep the legacy savepoint REST contract where jobId also identifies the restore source.\n        if (restoreMode == RestoreMode.SAVEPOINT && restoreSourceJobId == null) {\n            if (finalJobId != null) {\n                restoreSourceJobId = finalJobId;\n            } else {\n                throw new IllegalArgumentException(\n                        \"restoreSourceJobId is required when restoreMode=\" + restoreMode);\n            }\n        }\n        RestJobExecutionEnvironment restJobExecutionEnvironment =\n                new RestJobExecutionEnvironment(\n                        seaTunnelServer,\n                        jobConfig,\n                        config,\n                        node,\n                        restoreMode,\n                        restoreSourceJobId,\n                        finalJobId);\n        JobImmutableInformation jobImmutableInformation = restJobExecutionEnvironment.build();\n        long jobId = jobImmutableInformation.getJobId();\n        if (!seaTunnelServer.isMasterNode()) {\n\n            NodeEngineUtil.sendOperationToMasterNode(\n                            node.nodeEngine,","sourceCodeStart":1323,"sourceCodeEnd":1359,"githubUrl":"https://github.com/apache/seatunnel/blob/cf67b549a7a6c35fa0beb12d83c62892427ea919/seatunnel-engine/seatunnel-engine-server/src/main/java/org/apache/seatunnel/engine/server/rest/service/BaseService.java#L1323-L1359","documentation":"For SAVEPOINT restore mode submissions via REST, a restoreSourceJobId is mandatory. Legacy contract: if absent but jobId is present, jobId is reused as the restore source; if neither exists, IllegalArgumentException is thrown explaining that restoreSourceJobId is required for the given restoreMode.","triggerScenarios":"Submitting with restoreMode=SAVEPOINT while both restoreSourceJobId and jobId are missing/null in the request.","commonSituations":"Starting a job from a savepoint but forgetting to reference the source job; migrating jobs across clusters without carrying the original jobId; client SDK not mapping the field.","solutions":["Add restoreSourceJobId to the request pointing at the job whose savepoint you restore from","Alternatively pass jobId with the source job's id (legacy savepoint behavior)","Verify restoreMode value is intentional; use non-restore mode if you do not want savepoint restore"],"exampleFix":"// before\n{\"restoreMode\":\"SAVEPOINT\"}\n// after\n{\"restoreMode\":\"SAVEPOINT\",\"restoreSourceJobId\":\"863300353636515841\"}","handlingStrategy":"validation","validationCode":"if (restoreMode === 'SAVEPOINT' && !restoreSourceJobId && !jobId) throw new Error('restoreSourceJobId (or jobId) required for SAVEPOINT restore');","typeGuard":null,"tryCatchPattern":"try {\n    await post('/submit-job', payload);\n} catch (e) {\n    if (String(e).includes('restoreSourceJobId is required')) {\n        // add restoreSourceJobId and resend\n    }\n}","preventionTips":["Store source jobId when taking savepoints","Always pass restoreSourceJobId explicitly","Document restore flow in submission tooling"],"tags":["rest-api","savepoint","validation"],"backgroundTag":"missing-required-argument","analyzedSha":"cf67b549a7a6c35fa0beb12d83c62892427ea919","analyzedAt":"2026-09-10T21:44:55.265Z","contentChangedAt":"2026-09-10T21:44:55.265Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}