{"record":{"id":"d8f8d034a0a6591c","repo":"apache/seatunnel","slug":"failed-to-load-finished-job-dag-for-job","errorCode":null,"errorMessage":"Failed to load finished job DAG for job {}: {}","messagePattern":"Failed to load finished job DAG for job (.+?): (.+?)","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"seatunnel-engine/seatunnel-engine-server/src/main/java/org/apache/seatunnel/engine/server/rest/service/JobInfoService.java","lineNumber":165,"sourceCode":"\n    private String getFinishedJobMetricsJson(Long jobId) {\n        try {\n            IMap<Long, JobMetrics> finishedJobMetrics =\n                    nodeEngine.getHazelcastInstance().getMap(Constant.IMAP_FINISHED_JOB_METRICS);\n            JobMetrics metrics = finishedJobMetrics.getOrDefault(jobId, JobMetrics.empty());\n            return metrics == null ? JobMetrics.empty().toJsonString() : metrics.toJsonString();\n        } catch (Throwable t) {\n            log.warn(\"Failed to load finished job metrics for job {}: {}\", jobId, t.getMessage());\n            return JobMetrics.empty().toJsonString();\n        }\n    }\n\n    private JobDAGInfo getFinishedJobDAGInfo(\n            IMap<Long, JobDAGInfo> finishedJobDAGInfo, Long jobId) {\n        try {\n            return finishedJobDAGInfo.get(jobId);\n        } catch (Throwable t) {\n            log.warn(\"Failed to load finished job DAG for job {}: {}\", jobId, t.getMessage());\n            return null;\n        }\n    }\n\n    public JsonArray getRunningJobsJson() {\n        IMap<Long, JobInfo> values = getRunningJobInfoMap();\n        SeaTunnelServer seaTunnelServer = getSeaTunnelServer(true);\n        return values.entrySet().stream()\n                .filter(entry -> shouldShowAsRunningJob(seaTunnelServer, entry.getKey()))\n                .sorted(\n                        Comparator.comparing(\n                                entry -> entry.getValue().getInitializationTimestamp(),\n                                Comparator.reverseOrder()))\n                .map(\n                        jobInfoEntry ->\n                                convertToJson(\n                                        jobInfoEntry.getValue(), jobInfoEntry.getKey(), false))\n                .collect(JsonArray::new, JsonArray::add, JsonArray::add);","sourceCodeStart":147,"sourceCodeEnd":183,"githubUrl":"https://github.com/apache/seatunnel/blob/cf67b549a7a6c35fa0beb12d83c62892427ea919/seatunnel-engine/seatunnel-engine-server/src/main/java/org/apache/seatunnel/engine/server/rest/service/JobInfoService.java#L147-L183","documentation":"getFinishedJobDAGInfo fetches a finished job's DAG (JobDAGInfo) from the finished-job DAG IMap. On any Throwable it logs this warning and returns null, so callers render the finished job without DAG data instead of failing the whole REST response.","triggerScenarios":"Querying finished jobs REST API while the DAG entry is unreadable: Hazelcast member holding the partition is down, operation timeout, deserialization failure of JobDAGInfo, or the DAG map entry was evicted/expired.","commonSituations":"Cluster membership churn during query; mixed-version cluster where old serialized JobDAGInfo cannot be deserialized; large DAG entries timing out under load; map eviction policy removing old entries.","solutions":["Confirm all cluster members are healthy and partitions are not migrating; retry the query.","If deserialization errors, align SeaTunnel versions across members or purge stale finished-job DAG entries.","Increase Hazelcast operation call timeout for large DAG values.","Re-check whether the job's DAG was ever persisted; finished jobs from before persistence existed will simply be missing."],"exampleFix":"// before\n// JobDAGInfo dag = finishedJobDAGInfo.get(jobId);\n// after (service-internal behavior to mirror in callers)\n// try { dag = finishedJobDAGInfo.get(jobId); } catch (Throwable t) { log.warn(...); dag = null; }\n// if (dag == null) { render job without DAG }","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"JobDAGInfo dag = null;\ntry {\n    dag = getFinishedJobDAGInfo(finishedJobDAGInfo, jobId);\n} catch (Throwable t) {\n    log.warn(\"DAG unavailable for job {}\", jobId, t);\n}\nif (dag == null) { renderJobWithoutDag(jobId); }","preventionTips":["Handle null DAG gracefully in REST consumers","Align cluster versions to prevent JobDAGInfo deserialization failures","Check node health before querying finished-job data"],"tags":["hazelcast","rest-api","dag","deserialization"],"backgroundTag":"record-not-found","analyzedSha":"cf67b549a7a6c35fa0beb12d83c62892427ea919","analyzedAt":"2026-09-10T21:44:55.265Z","contentChangedAt":"2026-09-10T21:44:55.265Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}