{"record":{"id":"140197d3a901fbab","repo":"flowable/flowable-engine","slug":"comment-id-is-null","errorCode":null,"errorMessage":"comment id is null","messagePattern":"comment id is null","errorType":"validation","errorClass":"FlowableIllegalArgumentException","httpStatus":null,"severity":"error","filePath":"modules/flowable-engine/src/main/java/org/flowable/engine/impl/cmd/SaveCommentCmd.java","lineNumber":43,"sourceCode":"/**\n * @author Tijs Rademakers\n */\npublic class SaveCommentCmd implements Command<Void>, Serializable {\n\n    private static final long serialVersionUID = 1L;\n    protected CommentEntity comment;\n\n    public SaveCommentCmd(CommentEntity comment) {\n        this.comment = comment;\n    }\n\n    @Override\n    public Void execute(CommandContext commandContext) {\n        if (comment == null) {\n            throw new FlowableIllegalArgumentException(\"comment is null\");\n        }\n        if (comment.getId() == null) {\n            throw new FlowableIllegalArgumentException(\"comment id is null\");\n        } \n        \n        CommentEntityManager commentEntityManager = CommandContextUtil.getCommentEntityManager(commandContext);\n        \n        String eventMessage = comment.getFullMessage().replaceAll(\"\\\\s+\", \" \");\n        if (eventMessage.length() > 163) {\n            eventMessage = eventMessage.substring(0, 160) + \"...\";\n        }\n        comment.setMessage(eventMessage);\n\n        commentEntityManager.update(comment);\n\n        return null;\n    }\n}\n","sourceCodeStart":25,"sourceCodeEnd":59,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable-engine/src/main/java/org/flowable/engine/impl/cmd/SaveCommentCmd.java#L25-L59","documentation":"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.","triggerScenarios":"Calling TaskService.saveComment with a Comment built manually (never persisted) or from createComment where id was never assigned.","commonSituations":"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.","solutions":["Use taskService.createComment(taskId, processInstanceId, message) for new comments instead of saveComment.","Ensure the Comment being saved was fetched from the engine so its id is populated.","If constructing manually, insert it first so an id is generated."],"exampleFix":"// before\nCommentEntity c = new CommentEntityImpl();\nc.setFullMessage(\"hello\");\ntaskService.saveComment(c);\n// after\ntaskService.addComment(taskId, processInstanceId, \"hello\");","handlingStrategy":"validation","validationCode":"if (comment == null || comment.getId() == null) { throw new IllegalArgumentException(\"saveComment requires a persisted Comment with an id\"); }","typeGuard":"boolean isPersisted = comment != null && comment.getId() != null;","tryCatchPattern":"try {\n    taskService.saveComment(comment);\n} catch (FlowableIllegalArgumentException e) {\n    if (e.getMessage().contains(\"comment id is null\")) {\n        // create a new comment instead\n        taskService.addComment(taskId, processInstanceId, comment.getFullMessage());\n    }\n}","preventionTips":["Only call saveComment on comments fetched from the engine","Use createComment for comments you construct yourself","Keep the id field intact through any serialization/copying"],"tags":["validation","null-check","comment","entity-id"],"backgroundTag":"missing-required-argument","analyzedSha":"d6d39ce1c69ff244f2d9dc6af756a9b95e865586","analyzedAt":"2026-09-11T06:41:19.413Z","contentChangedAt":"2026-09-11T06:41:19.413Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}