flowable/flowable-engine · error · FlowableObjectNotFoundException

Comment with id '' doesn't exists.

Error message

Comment with id '' doesn't exists.

What it means

DeleteCommentCmd deletes a comment by id; if CommentEntityManager.findComment(commentId) returns null the command throws FlowableObjectNotFoundException with Comment.class. The comment id must refer to an existing persisted comment.

Solutions

  1. Verify existence before deleting: taskService.getProcessInstanceComments / getTaskComments and match the comment id, then delete only if found.
  2. Make the delete idempotent: catch FlowableObjectNotFoundException and treat the comment as already removed.
  3. Confirm the id passed is the comment's persisted id, not the task id.

Example fix

// before
taskService.deleteComment(commentId);
// after
try {
    taskService.deleteComment(commentId);
} catch (FlowableObjectNotFoundException e) {
    // comment already deleted; ignore
}
Defensive patterns

Strategy: try-catch

Validate before calling

List<Comment> comments = taskService.getTaskComments(taskId);
boolean exists = comments.stream().anyMatch(c -> commentId.equals(c.getId()));

Try / catch

try {
    taskService.deleteComment(commentId);
} catch (FlowableObjectNotFoundException e) {
    log.info("Comment {} already deleted", commentId);
}

Prevention

When it happens

Trigger: Calling TaskService.deleteComment(commentId) with an id that doesn't exist in ACT_HI_COMMENT — already deleted, invalid id, or id from a different database/engine.

Common situations: Client deletes a comment twice (double click / retry); stale id after a comment was removed by another user; passing a taskId/processInstanceId where a commentId is expected.

Understand the failure class

Background: "Not found" and "does not exist" errors: why "Task not found", "No such folder", and "Can't find" fire when a lookup comes back empty — this error's family across 14 libraries.

Related errors


AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11). Data as JSON: /api/errors/fe8ffa12394402a8. Report an issue: GitHub.

Appendix: source

Thrown at modules/flowable-engine/src/main/java/org/flowable/engine/impl/cmd/DeleteCommentCmd.java:56

    protected String processInstanceId;
    protected String commentId;

    public DeleteCommentCmd(String taskId, String processInstanceId, String commentId) {
        this.taskId = taskId;
        this.processInstanceId = processInstanceId;
        this.commentId = commentId;
    }

    @Override
    public Void execute(CommandContext commandContext) {
        ProcessEngineConfigurationImpl processEngineConfiguration = CommandContextUtil.getProcessEngineConfiguration(commandContext);
        CommentEntityManager commentManager = processEngineConfiguration.getCommentEntityManager();

        if (commentId != null) {
            // Delete for an individual comment
            Comment comment = commentManager.findComment(commentId);
            if (comment == null) {
                throw new FlowableObjectNotFoundException("Comment with id '" + commentId + "' doesn't exists.", Comment.class);
            }

            if (comment.getProcessInstanceId() != null) {
                ExecutionEntity execution = (ExecutionEntity) processEngineConfiguration.getExecutionEntityManager().findById(comment.getProcessInstanceId());
                if (execution != null && Flowable5Util.isFlowable5ProcessDefinitionId(commandContext, execution.getProcessDefinitionId())) {
                    Flowable5CompatibilityHandler compatibilityHandler = Flowable5Util.getFlowable5CompatibilityHandler();
                    compatibilityHandler.deleteComment(commentId, taskId, processInstanceId);
                    return null;
                }

            } else if (comment.getTaskId() != null) {
                Task task = processEngineConfiguration.getTaskServiceConfiguration().getTaskService().getTask(comment.getTaskId());
                if (task != null && task.getProcessDefinitionId() != null && Flowable5Util.isFlowable5ProcessDefinitionId(commandContext, task.getProcessDefinitionId())) {
                    Flowable5CompatibilityHandler compatibilityHandler = Flowable5Util.getFlowable5CompatibilityHandler();
                    compatibilityHandler.deleteComment(commentId, taskId, processInstanceId);
                    return null;
                }
            }

View on GitHub (pinned to d6d39ce1c6)