flowable/flowable-engine · error · FlowableIllegalArgumentException

comment id is null

Error message

comment id is null

What it means

SaveCommentCmd requires the Comment to have an id, since it performs an update of an existing comment row. It throws FlowableIllegalArgumentException('comment id is null') when a comment with a null id is saved, indicating the caller is treating a new (unsaved) comment as an existing one.

Source

Thrown at modules/flowable-engine/src/main/java/org/flowable/engine/impl/cmd/SaveCommentCmd.java:43

/**
 * @author Tijs Rademakers
 */
public class SaveCommentCmd implements Command<Void>, Serializable {

    private static final long serialVersionUID = 1L;
    protected CommentEntity comment;

    public SaveCommentCmd(CommentEntity comment) {
        this.comment = comment;
    }

    @Override
    public Void execute(CommandContext commandContext) {
        if (comment == null) {
            throw new FlowableIllegalArgumentException("comment is null");
        }
        if (comment.getId() == null) {
            throw new FlowableIllegalArgumentException("comment id is null");
        } 
        
        CommentEntityManager commentEntityManager = CommandContextUtil.getCommentEntityManager(commandContext);
        
        String eventMessage = comment.getFullMessage().replaceAll("\\s+", " ");
        if (eventMessage.length() > 163) {
            eventMessage = eventMessage.substring(0, 160) + "...";
        }
        comment.setMessage(eventMessage);

        commentEntityManager.update(comment);

        return null;
    }
}

View on GitHub (pinned to d6d39ce1c6)

Solutions

  1. Use taskService.createComment(taskId, processInstanceId, message) for new comments instead of saveComment.
  2. Ensure the Comment being saved was fetched from the engine so its id is populated.
  3. If constructing manually, insert it first so an id is generated.

Example fix

// before
CommentEntity c = new CommentEntityImpl();
c.setFullMessage("hello");
taskService.saveComment(c);
// after
taskService.addComment(taskId, processInstanceId, "hello");
Defensive patterns

Strategy: validation

Validate before calling

if (comment == null || comment.getId() == null) { throw new IllegalArgumentException("saveComment requires a persisted Comment with an id"); }

Type guard

boolean isPersisted = comment != null && comment.getId() != null;

Try / catch

try {
    taskService.saveComment(comment);
} catch (FlowableIllegalArgumentException e) {
    if (e.getMessage().contains("comment id is null")) {
        // create a new comment instead
        taskService.addComment(taskId, processInstanceId, comment.getFullMessage());
    }
}

Prevention

When it happens

Trigger: Calling TaskService.saveComment with a Comment built manually (never persisted) or from createComment where id was never assigned.

Common situations: Developers constructing a new Comment object in code and calling saveComment instead of createComment; deserialization dropping the id field; copying a comment entity without its id.

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


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