flowable/flowable-engine · error · ActivitiException

Cannot add a comment to a suspended execution

Error message

Cannot add a comment to a suspended execution

What it means

AddCommentCmd.execute rejects adding a comment to an execution (process instance) that is suspended, via getSuspendedExceptionMessage(). Suspended process instances are read-mostly; comment writes are treated as a state change and blocked.

Solutions

  1. Activate the instance first: runtimeService.activateProcessInstanceById(processInstanceId), then add the comment.
  2. Check suspension before commenting: runtimeService.createProcessInstanceQuery().processInstanceId(pid).singleResult().isSuspended().
  3. Queue the comment and post it after activation if suspension is temporary.

Example fix

// before
taskService.addComment(taskId, processInstanceId, "note");
// after
ProcessInstance pi = runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
if (pi != null && !pi.isSuspended()) {
    taskService.addComment(taskId, processInstanceId, "note");
}
Defensive patterns

Strategy: validation

Validate before calling

ProcessInstance pi = runtimeService.createProcessInstanceQuery()
    .processInstanceId(processInstanceId).singleResult();
if (pi != null && pi.isSuspended()) {
    throw new IllegalStateException("Process instance " + processInstanceId + " is suspended");
}

Try / catch

try {
    taskService.addComment(taskId, processInstanceId, message);
} catch (ActivitiException e) {
    if ("Cannot add a comment to a suspended execution".equals(e.getMessage())) {
        commentQueue.add(message); // post after activation
    } else { throw e; }
}

Prevention

When it happens

Trigger: Calling TaskService.addComment(taskId, processInstanceId, message) where the referenced process instance is in suspension state SUSPENDED (after suspendProcessInstanceById or via a suspended process definition).

Common situations: Audit/annotation jobs run while the instance is administratively paused; users post notes in a UI without checking the instance's suspension state; suspend/activate windows during maintenance.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


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

Appendix: source

Thrown at modules/flowable5-engine/src/main/java/org/activiti/engine/impl/cmd/AddCommentCmd.java:76

            if (task == null) {
                throw new ActivitiObjectNotFoundException("Cannot find task with id " + taskId, Task.class);
            }

            if (task.isSuspended()) {
                throw new ActivitiException(getSuspendedTaskException());
            }
        }

        if (processInstanceId != null) {
            ExecutionEntity execution = commandContext.getExecutionEntityManager().findExecutionById(processInstanceId);

            if (execution == null) {
                throw new ActivitiObjectNotFoundException("execution " + processInstanceId + " doesn't exist", Execution.class);
            }

            if (execution.isSuspended()) {
                throw new ActivitiException(getSuspendedExceptionMessage());
            }
        }

        String userId = Authentication.getAuthenticatedUserId();
        CommentEntity comment = new CommentEntity();
        comment.setUserId(userId);
        comment.setType((type == null) ? CommentEntity.TYPE_COMMENT : type);
        comment.setTime(commandContext.getProcessEngineConfiguration().getClock().getCurrentTime());
        comment.setTaskId(taskId);
        comment.setProcessInstanceId(processInstanceId);
        comment.setAction(Event.ACTION_ADD_COMMENT);

        String eventMessage = message.replaceAll("\\s+", " ");
        if (eventMessage.length() > 163) {
            eventMessage = eventMessage.substring(0, 160) + "...";
        }
        comment.setMessage(eventMessage);

View on GitHub (pinned to d6d39ce1c6)