flowable/flowable-engine · error · FlowableException
couldn't find a variable type that is able to serialize
Error message
couldn't find a variable type that is able to serialize
What it means
DefaultVariableTypes.findVariableType iterates the registered VariableType list and returns the first type whose isAbleToStore(value) is true. If no registered type can handle the value's Java class, it throws FlowableException 'couldn't find a variable type that is able to serialize <value>'.
Solutions
- Make the stored value implement a supported type (e.g. java.io.Serializable, String, Date, byte[]) or store a JSON/string representation
- Register a custom VariableType via processEngineConfiguration.setCustomPreVariableTypes / getVariableTypes, implementing isAbleToStore and conversions
- Check the value's class at runtime (implements Serializable?) before setting it as a variable
- Ensure required optional modules (JPA type, JSON type) are on the classpath and registered
Example fix
// before
execution.setVariable("data", new UnserializableDto(...)); // throws
// after
public class UnserializableDto implements Serializable { ... }
execution.setVariable("data", dto);
// or register:
config.setCustomPreVariableTypes(List.of(new DtoVariableType())); Defensive patterns
Strategy: validation
Validate before calling
boolean isStorableVariableValue(Object v) {
return v == null || v instanceof String || v instanceof Number || v instanceof Boolean
|| v instanceof byte[] || v instanceof java.util.Date
|| v instanceof java.io.Serializable; // plus any custom registered types
} Try / catch
try {
execution.setVariable("key", value);
} catch (org.flowable.common.engine.api.FlowableException e) {
if (e.getMessage().startsWith("couldn't find a variable type that is able to serialize")) {
execution.setVariable("key", jsonMapper.convertToJsonString(value));
} else {
throw e;
}
} Prevention
- Validate variable values implement Serializable or a natively supported type before setting
- Register custom VariableTypes for domain objects via setCustomPreVariableTypes
- Ensure optional modules (JPA/JSON types) are registered when storing those kinds of values
- Add an integration test setting every variable your processes use
When it happens
Trigger: Storing (setVariable/setVariableLocal) a value whose runtime class is not covered by the registered variable types — e.g. an unregistered custom bean, a POJO without a serializer, or a type removed by the JPA/Jackson type not being configured.
Common situations: Setting custom POJOs without registering a custom VariableType (e.g. SerializableType covers java.io.Serializable only if the object implements it); after upgrading Flowable where a default type (e.g. JPA entity type) is not registered; storing third-party objects that are not serializable.
Understand the failure class
Background: "is not a compatible type" / "cannot merge" errors: when a value's type doesn't match what the library requires — this error's family across 65 libraries.
Related errors
- Couldn't serialize value '' in variable ''
- Couldn't serialize value
- Failed to serialize to a RestVariable instance
- variable '
- variableName is null
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/8f9a3001218f97b5.
Report an issue: GitHub.
Appendix: source
Thrown at modules/flowable-variable-service/src/main/java/org/flowable/variable/service/impl/types/DefaultVariableTypes.java:68
this.typesMap.clear();
for (VariableType type : typesList) {
typesMap.put(type.getTypeName(), type);
}
}
@Override
public VariableType getVariableType(String typeName) {
return typesMap.get(typeName);
}
@Override
public VariableType findVariableType(Object value) {
for (VariableType type : typesList) {
if (type.isAbleToStore(value)) {
return type;
}
}
throw new FlowableException("couldn't find a variable type that is able to serialize " + value);
}
@Override
public int getTypeIndex(VariableType type) {
return typesList.indexOf(type);
}
@Override
public int getTypeIndex(String typeName) {
VariableType type = typesMap.get(typeName);
if (type != null) {
return getTypeIndex(type);
} else {
return -1;
}
}
@OverrideView on GitHub (pinned to d6d39ce1c6)