{"record":{"id":"a8782e442685a67a","repo":"jeecgboot/JeecgBoot","slug":"jobinfo-glue-jobid-invalid","errorCode":"jobinfo_glue_jobid_invalid","errorMessage":"jobinfo_glue_jobid_invalid","messagePattern":"jobinfo_glue_jobid_invalid","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"jeecg-boot/jeecg-server-cloud/jeecg-visual/jeecg-cloud-xxljob/src/main/java/com/xxl/job/admin/business/controller/JobCodeController.java","lineNumber":49,"sourceCode":" * @author xuxueli 2015-12-19 16:13:16\n */\n@Controller\n@RequestMapping(\"/jobcode\")\npublic class JobCodeController {\n\tprivate static final Logger logger = LoggerFactory.getLogger(JobCodeController.class);\n\t\n\t@Resource\n\tprivate XxlJobInfoMapper xxlJobInfoMapper;\n\t@Resource\n\tprivate XxlJobLogGlueMapper xxlJobLogGlueMapper;\n\n\t@RequestMapping\n\tpublic String index(HttpServletRequest request, Model model, @RequestParam(\"jobId\") int jobId) {\n\t\tXxlJobInfo jobInfo = xxlJobInfoMapper.loadById(jobId);\n\t\tList<XxlJobLogGlue> jobLogGlues = xxlJobLogGlueMapper.findByJobId(jobId);\n\n\t\tif (jobInfo == null) {\n\t\t\tthrow new RuntimeException(I18nUtil.getString(\"jobinfo_glue_jobid_invalid\"));\n\t\t}\n\t\tif (GlueTypeEnum.BEAN == GlueTypeEnum.match(jobInfo.getGlueType())) {\n\t\t\tthrow new RuntimeException(I18nUtil.getString(\"jobinfo_glue_gluetype_invalid\"));\n\t\t}\n\n\t\t// valid jobGroup permission\n\t\tJobGroupPermissionUtil.validJobGroupPermission(request, jobInfo.getJobGroup());\n\n\t\t// Glue类型-字典\n\t\tmodel.addAttribute(\"GlueTypeEnum\", GlueTypeEnum.values());\n\n\t\tmodel.addAttribute(\"jobInfo\", jobInfo);\n\t\tmodel.addAttribute(\"jobLogGlues\", jobLogGlues);\n\t\treturn \"business/job.code\";\n\t}\n\t\n\t@RequestMapping(\"/save\")\n\t@ResponseBody","sourceCodeStart":31,"sourceCodeEnd":67,"githubUrl":"https://github.com/jeecgboot/JeecgBoot/blob/96fb33f5ec68516da0b0147da06b2eb0419e063a/jeecg-boot/jeecg-server-cloud/jeecg-visual/jeecg-cloud-xxljob/src/main/java/com/xxl/job/admin/business/controller/JobCodeController.java#L31-L67","documentation":"Thrown by JobCodeController.index when xxlJobInfoMapper.loadById(jobId) returns null, meaning the requested job ID does not exist in the xxl_job_info table. This controller handles the GLUE script editor view — it loads job metadata to display the code editing page. A null jobInfo means the job was deleted, the ID is wrong, or the database is out of sync. The error message comes from i18n key 'jobinfo_glue_jobid_invalid'.","triggerScenarios":"Navigating to the GLUE code editor URL with a jobId that doesn't exist: /jobcode?jobId=99999. The job was deleted but the user's browser still has a cached bookmark/link. A concurrent admin deleted the job between the user opening the job list and clicking into the code editor. The jobId parameter was tampered with.","commonSituations":"Stale bookmark to a deleted job's GLUE editor. URL manipulation by users. Race condition between job deletion and another user accessing the code editor. Database inconsistency where xxl_job_log_glue references a jobId that no longer exists in xxl_job_info.","solutions":["Verify the job exists: SELECT id, job_desc, glue_type FROM xxl_job_info WHERE id = <jobId>.","If the job was deleted, navigate back to the job list and select an existing job.","Clear stale bookmarks and use the job list page to access GLUE code editors.","Add client-side validation to check if the job exists before navigating to the code editor (AJAX call to job list API)."],"exampleFix":"// before: direct navigation to potentially stale URL\nwindow.location.href = '/jobcode?jobId=' + jobId;\n\n// after: validate job exists before navigating\nconst exists = await checkJobExists(jobId);\nif (!exists) {\n    alert('任务不存在或已被删除');\n    refreshJobList();\n    return;\n}\nwindow.location.href = '/jobcode?jobId=' + jobId;","handlingStrategy":"validation","validationCode":"// Validate job exists before navigating to GLUE code editor\npublic boolean jobExists(int jobId) {\n    return xxlJobInfoMapper.loadById(jobId) != null;\n}\n\n// In controller/API:\nif (!jobExists(jobId)) {\n    return Response.ofFail(I18nUtil.getString(\"jobinfo_glue_jobid_invalid\"));\n}","typeGuard":null,"tryCatchPattern":"try {\n    // Controller method body — navigation to job code page\n    return \"business/job.code\";\n} catch (RuntimeException e) {\n    if (e.getMessage().contains(\"jobinfo_glue_jobid_invalid\")) {\n        // Redirect to job list with error message\n        model.addAttribute(\"error\", \"Job does not exist\");\n        return \"redirect:/jobinfo\";\n    }\n    throw e;\n}","preventionTips":["Before navigating to the GLUE code editor, verify the jobId is valid via an AJAX call.","Clear stale bookmarks that reference deleted jobs.","Refresh the job list after deletions to avoid stale links.","Handle the RuntimeException gracefully on the frontend with a user-friendly message."],"tags":["xxl-job","glue","job-management","validation","i18n"],"backgroundTag":null,"analyzedSha":"96fb33f5ec68516da0b0147da06b2eb0419e063a","analyzedAt":"2026-08-14T00:04:16.786Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}