{"record":{"id":"581c175627f5d47e","repo":"apache/dolphinscheduler","slug":"50038","errorCode":"50038","errorMessage":"update task definition error","messagePattern":"update task definition error","errorType":"error_code","errorClass":"ServiceException","httpStatus":null,"severity":"error","filePath":"dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/impl/TaskDefinitionServiceImpl.java","lineNumber":389,"sourceCode":"                    try {\n                        permissionCheck.checkPermission();\n                    } catch (Exception e) {\n                        log.error(\"Resources permission check error, resourceIds:{}.\", resourceIds, e);\n                        throw new ServiceException(Status.RESOURCE_NOT_EXIST_OR_NO_PERMISSION);\n                    }\n                }\n                taskDefinition.setFlag(Flag.YES);\n                taskDefinitionLog.setFlag(Flag.YES);\n                break;\n            default:\n                log.warn(\"Parameter releaseState is invalid.\");\n                throw new ServiceException(Status.REQUEST_PARAMS_NOT_VALID_ERROR, Constants.RELEASE_STATE);\n        }\n        boolean updateSuccess = taskDefinitionDao.updateById(taskDefinition);\n        int updateLog = taskDefinitionLogMapper.updateById(taskDefinitionLog);\n        if (updateSuccess != (updateLog == 1)) {\n            log.error(\"Update taskDefinition state or taskDefinitionLog state error, taskDefinitionCode:{}.\", code);\n            throw new ServiceException(Status.UPDATE_TASK_DEFINITION_ERROR);\n        }\n        log.info(\"Update taskDefinition state or taskDefinitionLog state to complete, taskDefinitionCode:{}.\",\n                code);\n    }\n\n    @Override\n    public void deleteTaskByWorkflowDefinitionCode(long workflowDefinitionCode, int workflowDefinitionVersion) {\n        List<WorkflowTaskRelation> workflowTaskRelations = workflowTaskRelationService\n                .queryByWorkflowDefinitionCode(workflowDefinitionCode, workflowDefinitionVersion);\n        if (CollectionUtils.isEmpty(workflowTaskRelations)) {\n            return;\n        }\n        // delete task definition\n        Set<Long> needToDeleteTaskDefinitionCodes = new HashSet<>();\n        for (WorkflowTaskRelation workflowTaskRelation : workflowTaskRelations) {\n            needToDeleteTaskDefinitionCodes.add(workflowTaskRelation.getPreTaskCode());\n            needToDeleteTaskDefinitionCodes.add(workflowTaskRelation.getPostTaskCode());\n        }","sourceCodeStart":371,"sourceCodeEnd":407,"githubUrl":"https://github.com/apache/dolphinscheduler/blob/02eac45a1b6676e639fcbfb4be2243de5771b05d/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/impl/TaskDefinitionServiceImpl.java#L371-L407","documentation":"ServiceException(Status.UPDATE_TASK_DEFINITION_ERROR, 50038) signals an inconsistent update in releaseTaskDefinition: `updateSuccess` (taskDefinitionDao.updateById) and `updateLog == 1` (taskDefinitionLogMapper.updateById) disagree, so the definition and its version log are out of sync. The library throws instead of leaving partial state.","triggerScenarios":"updateById on T_DS_TASK_DEFINITION succeeds but the log update affects 0 rows (or vice versa) during releaseTaskDefinition — e.g., the TaskDefinitionLog entity is stale so its id no longer matches a row.","commonSituations":"Concurrent modification deleting/updating the log row between query and update; log row missing an id after manual insertion; DB replication lag or deadlock causing one update to fail; transaction isolation issues.","solutions":["Verify both T_DS_TASK_DEFINITION and T_DS_TASK_DEFINITION_LOG rows exist with matching code+version, then retry the release","Wrap the two updates in a single transaction so they succeed or fail together","Check for concurrent jobs/locks touching the task definition and retry when idle","Inspect the TaskDefinitionLog id field — re-query the log row before updating instead of reusing a stale entity"],"exampleFix":"// before: two independent updates, mismatch possible\nboolean updateSuccess = taskDefinitionDao.updateById(taskDefinition);\nint updateLog = taskDefinitionLogMapper.updateById(taskDefinitionLog);\n// after: make them transactional and re-check row counts together\n@Transactional\nvoid release(...) {\n    if (!(taskDefinitionDao.updateById(taskDefinition) && taskDefinitionLogMapper.updateById(taskDefinitionLog) == 1)) {\n        throw new ServiceException(Status.UPDATE_TASK_DEFINITION_ERROR);\n    }\n}","handlingStrategy":"retry","validationCode":"// pre-check both rows exist and are current\nif (taskDefinitionDao.queryByCode(code) == null ||\n    taskDefinitionLogMapper.queryByDefinitionCodeAndVersion(code, version) == null) {\n    throw new IllegalStateException(\"definition/log rows out of sync before update\");\n}","typeGuard":"boolean rowsInSync(long code, int version) {\n    TaskDefinition td = taskDefinitionDao.queryByCode(code);\n    return td != null && taskDefinitionLogMapper.queryByDefinitionCodeAndVersion(code, td.getVersion()) != null;\n}","tryCatchPattern":"try {\n    service.releaseTaskDefinition(loginUser, projectCode, code, state);\n} catch (ServiceException e) {\n    if (e.getCode() == Status.UPDATE_TASK_DEFINITION_ERROR.getCode()) {\n        // verify row states, resolve contention, then retry once\n    }\n    throw e;\n}","preventionTips":["Run the two updates in one transaction to avoid partial state","Avoid concurrent edits to the same task definition (use UI locks/serialization)","Re-query the log row immediately before updating instead of caching entities","Monitor for DB deadlocks/replication lag on the definition tables"],"tags":["database","inconsistent-update","task-definition","dolphinscheduler"],"backgroundTag":"database-write-failed","analyzedSha":"02eac45a1b6676e639fcbfb4be2243de5771b05d","analyzedAt":"2026-09-06T17:43:00.555Z","contentChangedAt":"2026-09-06T17:43:00.555Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}