flowable/flowable-engine · error · ActivitiIllegalArgumentException
null value cannot be saved
Error message
null value cannot be saved
What it means
JPAEntityMappings serializes JPA entity variables for persistence. getJPAClassString extracts the entity class name for storage; it refuses a null value because a null cannot carry JPA metadata and cannot be persisted as a JPA entity variable.
Solutions
- Ensure the value is a non-null JPA entity before setting the variable
- Guard the caller: if the entity is null, set the variable to null explicitly via a null-typed variable instead of the JPA mapping, or remove the variable
- Fix the upstream fetch so the entity is loaded before it reaches variable serialization
Example fix
// before
runtimeService.setVariable(executionId, "order", possiblyNullOrder);
// after
if (possiblyNullOrder != null) {
runtimeService.setVariable(executionId, "order", possiblyNullOrder);
} else {
runtimeService.setVariable(executionId, "order", null);
} Defensive patterns
Strategy: validation
Validate before calling
if (value == null) {
throw new IllegalArgumentException("Cannot store null as JPA entity variable");
}
runtimeService.setVariable(id, "order", value); Type guard
boolean isNonNull(Object v) { return v != null; } Try / catch
try {
runtimeService.setVariable(id, "order", value);
} catch (ActivitiIllegalArgumentException e) {
if (e.getMessage().contains("null value cannot be saved")) {
runtimeService.setVariable(id, "order", null);
} else { throw e; }
} Prevention
- Null-check entities before assigning process variables
- Avoid setting variables from expressions that can evaluate to null
- Log entity fetch results so null returns are caught early
When it happens
Trigger: Calling getJPAClassString(null) directly, or storing a null variable through the JPA entity variable type mapping (e.g. taskService.setVariable / runtimeService.setVariable resolved to the JPA type) with a null value.
Common situations: A process variable set from an expression or delegate field that evaluates to null (entity not yet loaded/found); passing a result of em.find() that returned null; spring bean method returning null wired as a variable.
Related errors
- decisionTableReferenceKey expression resolves to an empty…
- Value of primary key for JPA-Entity cannot be null
- Value of primary key for JPA-Entity cannot be null
- byte array for resource
- Cannot access id method/field for JPA Entity
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/a752346541d1eae8.
Report an issue: GitHub.
Appendix: source
Thrown at modules/flowable5-engine/src/main/java/org/activiti/engine/impl/variable/JPAEntityMappings.java:71
}
public EntityMetaData getEntityMetaData(Class<?> clazz) {
EntityMetaData metaData = classMetaDatamap.get(clazz.getName());
if (metaData == null) {
// Class not present in meta-data map, create metaData for it and add
metaData = scanClass(clazz);
classMetaDatamap.put(clazz.getName(), metaData);
}
return metaData;
}
private EntityMetaData scanClass(Class<?> clazz) {
return enitityScanner.scanClass(clazz);
}
public String getJPAClassString(Object value) {
if (value == null) {
throw new ActivitiIllegalArgumentException("null value cannot be saved");
}
EntityMetaData metaData = getEntityMetaData(value.getClass());
if (!metaData.isJPAEntity()) {
throw new ActivitiIllegalArgumentException("Object is not a JPA Entity: class='" + value.getClass() + "', " + value);
}
// Extract the class from the Entity instance
return metaData.getEntityClass().getName();
}
public String getJPAIdString(Object value) {
EntityMetaData metaData = getEntityMetaData(value.getClass());
if (!metaData.isJPAEntity()) {
throw new ActivitiIllegalArgumentException("Object is not a JPA Entity: class='" + value.getClass() + "', " + value);
}
Object idValue = getIdValue(value, metaData);
return getIdString(idValue);View on GitHub (pinned to d6d39ce1c6)