elunez/eladmin · error · BadRequestException
子任务中不能添加当前任务ID
Error message
子任务中不能添加当前任务ID
What it means
On job update, if the subTask field (comma-separated list of job IDs to chain after this job) is non-blank, QuartzJobServiceImpl.update splits it on both ',' and the full-width ',' and rejects the request if the resulting list contains the job's own id. Allowing it would make the job re-trigger itself, causing infinite recursive execution.
Source
Thrown at eladmin-system/src/main/java/me/zhengjie/modules/quartz/service/impl/QuartzJobServiceImpl.java:97
@Transactional(rollbackFor = Exception.class)
public void create(QuartzJob resources) {
if (!CronExpression.isValidExpression(resources.getCronExpression())){
throw new BadRequestException("cron表达式格式错误");
}
resources = quartzJobRepository.save(resources);
quartzManage.addJob(resources);
}
@Override
@Transactional(rollbackFor = Exception.class)
public void update(QuartzJob resources) {
if (!CronExpression.isValidExpression(resources.getCronExpression())){
throw new BadRequestException("cron表达式格式错误");
}
if(StringUtils.isNotBlank(resources.getSubTask())){
List<String> tasks = Arrays.asList(resources.getSubTask().split("[,,]"));
if (tasks.contains(resources.getId().toString())) {
throw new BadRequestException("子任务中不能添加当前任务ID");
}
}
resources = quartzJobRepository.save(resources);
quartzManage.updateJobCron(resources);
}
@Override
public void updateIsPause(QuartzJob quartzJob) {
// 置换暂停状态
if (quartzJob.getIsPause()) {
quartzManage.resumeJob(quartzJob);
quartzJob.setIsPause(false);
} else {
quartzManage.pauseJob(quartzJob);
quartzJob.setIsPause(true);
}
quartzJobRepository.save(quartzJob);
}View on GitHub (pinned to 55fbf70595)
Solutions
- Remove the job's own ID from its subTask field; subTask should only contain OTHER job IDs to run after completion.
- If chaining behavior on itself is genuinely needed, restructure into two jobs that reference each other's IDs (and re-check whether recursion is intended at all).
- Filter the current ID out in the frontend picker before submitting.
Example fix
// before
{"id": "5", "subTask": "5,8,9"} // self-reference -> rejected
// after
{"id": "5", "subTask": "8,9"} Defensive patterns
Strategy: validation
Validate before calling
// strip self-reference before saving
List<String> ids = Arrays.stream(subTask.split("[,,]"))
.map(String::trim).filter(s -> !s.equals(String.valueOf(jobId))).collect(Collectors.toList());
String safe = String.join(",", ids); Type guard
boolean subTaskIsSafe(String subTask, Long selfId) {
if (StringUtils.isBlank(subTask)) return true;
return Arrays.stream(subTask.split("[,,]"))
.map(String::trim)
.noneMatch(s -> s.equals(String.valueOf(selfId)));
} Prevention
- Exclude the current job from the subTask picker's options list.
- Document in the UI that subTask = jobs to run AFTER this one, dependencies only.
- Beware both comma styles (',' and ',') when validating manually.
When it happens
Trigger: PUT /api/quartz/jobs with subTask containing the job's own ID, e.g. updating job id=5 with subTask='5,6' or '5,6'. String comparison is used, so both '5' and any exact string match on the ID triggers it.
Common situations: Copy-pasting a job's full subTask chain into itself when cloning configurations; UI dropdown listing all jobs including the current one; misunderstanding subTask as a dependency list and adding the parent.
Related errors
- A new quartzJob cannot already have an ID
- 非法的 Bean,请重新输入!
- cron表达式格式错误
- 文件超出规定大小:{maxSize}MB
- {entity} 不存在: {parameter} is {value}
AI-assisted analysis of elunez/eladmin@55fbf70595 (2026-08-14).
Data as JSON: /api/errors/8ddf8b9ac9de034a.
Report an issue: GitHub.