{"record":{"id":"d59dd8f12c3ffa4f","repo":"jeecgboot/JeecgBoot","slug":"joblog-logid-invalid","errorCode":"joblog_logid_invalid","errorMessage":"joblog_logid_invalid","messagePattern":"joblog_logid_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/JobLogController.java","lineNumber":268,"sourceCode":"\n\t\tList<Long> logIds = null;\n\t\tdo {\n\t\t\tlogIds = xxlJobLogMapper.findClearLogIds(jobGroup, jobId, clearBeforeTime, clearBeforeNum, 1000);\n\t\t\tif (logIds!=null && !logIds.isEmpty()) {\n\t\t\t\txxlJobLogMapper.clearLog(logIds);\n\t\t\t}\n\t\t} while (logIds!=null && !logIds.isEmpty());\n\n\t\treturn Response.ofSuccess();\n\t}\n\n\t@RequestMapping(\"/logDetailPage\")\n\tpublic String logDetailPage(HttpServletRequest request, @RequestParam(\"id\") long id, Model model){\n\n\t\t// base check\n\t\tXxlJobLog jobLog = xxlJobLogMapper.load(id);\n\t\tif (jobLog == null) {\n\t\t\tthrow new RuntimeException(I18nUtil.getString(\"joblog_logid_invalid\"));\n\t\t}\n\n\t\t// valid permission\n\t\tJobGroupPermissionUtil.validJobGroupPermission(request, jobLog.getJobGroup());\n\n\t\t// load jobInfo\n\t\tXxlJobInfo jobInfo = xxlJobInfoMapper.loadById(jobLog.getJobId());\n\n\t\t// data\n\t\tmodel.addAttribute(\"triggerCode\", jobLog.getTriggerCode());\n\t\tmodel.addAttribute(\"handleCode\", jobLog.getHandleCode());\n\t\tmodel.addAttribute(\"logId\", jobLog.getId());\n\t\tmodel.addAttribute(\"jobInfo\", jobInfo);\n\t\treturn \"business/log.detail\";\n\t}\n\n\t@RequestMapping(\"/logDetailCat\")\n\t@ResponseBody","sourceCodeStart":250,"sourceCodeEnd":286,"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/JobLogController.java#L250-L286","documentation":"Thrown by JobLogController.logDetailPage when xxlJobLogMapper.load(id) returns null. This means the requested execution log ID does not exist in xxl_job_log — the log was either purged by the log retention policy, the ID is wrong, or the log was never created. The log detail page cannot render without the log record. Message from i18n key 'joblog_logid_invalid'.","triggerScenarios":"User clicks a log detail link for an old execution that has been cleaned up by XXL-Job's log retention (logRetentionDays). Manually navigating to /logDetailPage?id=99999 with a non-existent log ID. The log was partially written and then purged due to DB cleanup. Concurrent log cleanup (scheduled purge job) deleted the log between the list render and detail click.","commonSituations":"Old log entries past the retention window (default 30 days). Database cleanup or manual deletion of xxl_job_log rows. User bookmarked a specific log detail page that has since expired. Cron-based log cleanup ran between page load and detail navigation.","solutions":["Verify the log exists: SELECT id, trigger_time, handle_code FROM xxl_job_log WHERE id = <id>.","If the log was purged, it is gone — check the log retention setting (XXL-Job admin → System Configuration → logRetentionDays) and increase it if needed.","If the log should exist, check the log cleanup job configuration — it may be running too aggressively.","On the frontend, handle this error gracefully with a 'Log not found or expired' message rather than showing a raw stack trace."],"exampleFix":"// before: direct navigation without existence check\nwindow.open('/logDetailPage?id=' + logId);\n\n// after: handle missing log gracefully\ntry {\n  const res = await api.get(`/joblog/logDetailCat?id=${logId}`);\n  if (res.data.code !== 200) {\n    alert('Log not found or has been purged.');\n    return;\n  }\n  window.open('/logDetailPage?id=' + logId);\n} catch (e) {\n  alert('Failed to load log detail.');\n}","handlingStrategy":"validation","validationCode":"// Validate log exists before opening detail page\npublic boolean logExists(long id) {\n    return xxlJobLogMapper.load(id) != null;\n}","typeGuard":null,"tryCatchPattern":"try {\n    return \"business/job.log.detail\";\n} catch (RuntimeException e) {\n    if (e.getMessage().contains(\"joblog_logid_invalid\")) {\n        model.addAttribute(\"error\", \"Log not found or has been purged.\");\n        return \"redirect:/joblog\";\n    }\n    throw e;\n}","preventionTips":["Increase logRetentionDays in XXL-Job system configuration if logs are being purged too quickly.","Handle missing log errors gracefully on the frontend with a 'log expired' message.","Avoid bookmarking individual log detail pages — they are transient by nature.","Export critical logs to external storage if long-term retention is needed."],"tags":["xxl-job","job-log","validation","log-retention","i18n"],"backgroundTag":null,"analyzedSha":"96fb33f5ec68516da0b0147da06b2eb0419e063a","analyzedAt":"2026-08-14T00:04:16.786Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}