{"record":{"id":"57739eb1e8eee035","repo":"apache/dolphinscheduler","slug":"projectuser-must-not-be-null","errorCode":null,"errorMessage":"projectUser must not be null","messagePattern":"projectUser must not be null","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"warning","filePath":"dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/AlertDao.java","lineNumber":206,"sourceCode":"        alert.setUpdateTime(new Date());\n        alert.setAlertType(AlertType.FAULT_TOLERANCE_WARNING);\n        alert.setSign(generateSign(alert));\n        // we use this method to avoid insert duplicate alert(issue #5525)\n        // we modified this method to optimize performance(issue #9174)\n        Date crashAlarmSuppressionStartTime = Date.from(\n                LocalDateTime.now().plusMinutes(-crashAlarmSuppression).atZone(ZoneId.systemDefault()).toInstant());\n        alertMapper.insertAlertWhenServerCrash(alert, crashAlarmSuppressionStartTime);\n    }\n\n    /**\n     * workflow time out alert\n     *\n     * @param workflowInstance workflowInstance\n     * @param projectUser     projectUser\n     */\n    public void sendWorkflowTimeoutAlert(WorkflowInstance workflowInstance, ProjectUser projectUser) {\n        if (projectUser == null) {\n            throw new IllegalArgumentException(\"projectUser must not be null\");\n        }\n        if (workflowInstance.getWarningGroupId() == null) {\n            throw new IllegalArgumentException(\"warningGroupId of the workflow instance must not be null\");\n        }\n\n        int alertGroupId = workflowInstance.getWarningGroupId();\n        Alert alert = new Alert();\n        List<WorkflowAlertContent> workflowAlertContentList = new ArrayList<>(1);\n        WorkflowAlertContent workflowAlertContent = WorkflowAlertContent.builder()\n                .projectCode(projectUser.getProjectCode())\n                .projectName(projectUser.getProjectName())\n                .owner(projectUser.getUserName())\n                .workflowInstanceId(workflowInstance.getId())\n                .workflowDefinitionCode(workflowInstance.getWorkflowDefinitionCode())\n                .workflowInstanceName(workflowInstance.getName())\n                .commandType(workflowInstance.getCommandType())\n                .workflowExecutionStatus(workflowInstance.getState())\n                .runTimes(workflowInstance.getRunTimes())","sourceCodeStart":188,"sourceCodeEnd":224,"githubUrl":"https://github.com/apache/dolphinscheduler/blob/02eac45a1b6676e639fcbfb4be2243de5771b05d/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/AlertDao.java#L188-L224","documentation":"AlertDao.sendWorkflowTimeoutAlert() requires the ProjectUser of the workflow's owner to construct the alert content (project name, user name). If a null ProjectUser is passed, it immediately fails fast with IllegalArgumentException rather than producing a partial alert.","triggerScenarios":"A caller (e.g. workflow timeout warning handling in the master/worker alert path) queries the project/user and receives null (project deleted, user removed, or query on wrong projectCode), then passes it to sendWorkflowTimeoutAlert.","commonSituations":"Workflow instance belongs to a project that was deleted while the instance was still running; user account removed; refactored caller passing an unpopulated object; DB lookups returning null for orphaned workflow instances.","solutions":["Ensure the caller fetches ProjectUser via the project code and handles a null result before calling sendWorkflowTimeoutAlert.","Check the project_code of the workflow instance exists in the project table.","Skip or degrade the timeout alert when the project/user no longer exists instead of passing null.","Verify the mapping/query used to build ProjectUser returns all fields."],"exampleFix":"// before\nalertDao.sendWorkflowTimeoutAlert(workflowInstance, projectUser); // may be null\n// after\nif (projectUser != null) {\n    alertDao.sendWorkflowTimeoutAlert(workflowInstance, projectUser);\n}","handlingStrategy":"validation","validationCode":"if (projectUser == null) {\n    log.warn(\"Skip workflow timeout alert: no project user for instance {}\", workflowInstance.getId());\n    return;\n}","typeGuard":"boolean hasProjectUser(WorkflowInstance wf, ProjectUser pu) { return pu != null; }","tryCatchPattern":"try {\n    alertDao.sendWorkflowTimeoutAlert(workflowInstance, projectUser);\n} catch (IllegalArgumentException e) {\n    log.warn(\"Workflow timeout alert skipped: {}\", e.getMessage());\n}","preventionTips":["Never delete projects/users with running workflow instances without cleanup.","Null-check ProjectUser lookups at call sites.","Write integration tests for alert paths with orphaned instances."],"tags":["alerting","null-check","validation"],"backgroundTag":"null-argument","analyzedSha":"02eac45a1b6676e639fcbfb4be2243de5771b05d","analyzedAt":"2026-09-06T17:43:00.555Z","contentChangedAt":"2026-09-06T17:43:00.555Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}