flowable/flowable-engine · error · FlowableIllegalArgumentException

documentation expression does not resolve to a string:

Error message

documentation expression does not resolve to a string: 

What it means

The cmmn:documentation / task description attribute was written as an expression (e.g. ${...}). When Flowable evaluates it during human task creation, the result must be a String; any other type (Integer, Date, etc.) is rejected by throwing FlowableIllegalArgumentException so a wrong-typed value is not silently stored on the task.

Source

Thrown at modules/flowable-cmmn-engine/src/main/java/org/flowable/cmmn/engine/impl/behavior/impl/HumanTaskActivityBehavior.java:212

                if (name instanceof String) {
                    taskEntity.setName((String) name);
                } else {
                    throw new FlowableIllegalArgumentException("name expression does not resolve to a string: " + beforeContext.getName());
                }
            }
        }
    }

    protected void handleTaskDescription(PlanItemInstanceEntity planItemInstanceEntity, ExpressionManager expressionManager, 
                    TaskEntity taskEntity, CreateHumanTaskBeforeContext beforeContext) {
        
        if (StringUtils.isNotEmpty(beforeContext.getDescription())) {
            Object description = expressionManager.createExpression(beforeContext.getDescription()).getValue(planItemInstanceEntity);
            if (description != null) {
                if (description instanceof String) {
                    taskEntity.setDescription((String) description);
                } else {
                    throw new FlowableIllegalArgumentException("documentation expression does not resolve to a string: " + beforeContext.getDescription());
                }
            }
        }
    }

    protected void handleAssignee(PlanItemInstanceEntity planItemInstanceEntity, TaskService taskService,
            ExpressionManager expressionManager, TaskEntity taskEntity, PlanItemInstanceEntityManager planItemInstanceEntityManager,
            CreateHumanTaskBeforeContext beforeContext, MigrationContext migrationContext) {
        
        String assigneeStringValue = null;
        if (migrationContext != null && migrationContext.getAssignee() != null) {
            assigneeStringValue = migrationContext.getAssignee();
            
        } else if (StringUtils.isNotEmpty(beforeContext.getAssignee())) {
            assigneeStringValue = beforeContext.getAssignee();
        }
        
        if (StringUtils.isNotEmpty(assigneeStringValue)) {

View on GitHub (pinned to d6d39ce1c6)

Solutions

  1. Make the description expression resolve to a String, e.g. wrap it: ${toString(myVar)} or use a String variable.
  2. Fix the referenced variable/bean so its value is a String (or convert it at the source).
  3. If a static description is intended, remove the ${...} expression and write plain text in the documentation element.
  4. Catch FlowableIllegalArgumentException around the plan item start and log the offending expression for correction.

Example fix

// before (CMMN XML)
<cmmn:documentation>${dueDate}</cmmn:documentation>
// after
<cmmn:documentation>${dueDate.toString()}</cmmn:documentation>
Defensive patterns

Strategy: type-guard

Validate before calling

Object desc = expressionManager.createExpression(descStr).getValue(scope);
if (desc != null && !(desc instanceof String)) throw new IllegalArgumentException("Description must resolve to String, got " + desc.getClass());

Type guard

boolean isValidDescription(Object v) { return v == null || v instanceof String; }

Try / catch

try {
    runtimeService.createPlanItemInstanceQuery()...; // start/execute plan item
} catch (FlowableIllegalArgumentException e) {
    if (e.getMessage().startsWith("documentation expression")) {
        log.error("Bad description expression: {}", e.getMessage());
    }
}

Prevention

When it happens

Trigger: HumanTaskActivityBehavior.execute -> handleTaskDescription, when the plan item's TaskDefinition has a non-empty description whose expression evaluates to a non-null, non-String object.

Common situations: Description expression like ${someDate} or ${count} resolving to a Date/Number; bean method returning non-String; typo pointing at the wrong variable; copy-pasting a description expression that worked for a form key into the description field.

Understand the failure class

Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.

Related errors


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