flowable/flowable-engine · critical · FlowableException

unknown variable type name

Error message

unknown variable type name 

What it means

IbatisVariableTypeHandler.getResult(ResultSet, String) throws FlowableException when the TYPE_ column read from the database does not map to any registered VariableType (variableTypes.getVariableType returns null while typeName is non-null). This means the row references a variable type name unknown to the current engine configuration, so it cannot be deserialized safely.

Solutions

  1. Register the missing VariableType in the engine configuration (customPostVariableTypes / variableTypes) so getVariableType finds it
  2. Align Flowable versions across all nodes writing/reading the variable tables
  3. Inspect the offending row's TYPE_ column value and fix or migrate the data; also verify which query/column triggers it (getResult with columnName keeps returning null for NULL type names, but throws for unknown non-null names)

Example fix

// before (type missing at startup)
ProcessEngineConfiguration cfg = ProcessEngineConfiguration
    .createProcessEngineConfigurationFromResource("flowable.cfg.xml");
// after
cfg.setCustomPostVariableTypes(
    Collections.singletonList(new MyCustomVariableType()));
// so IbatisVariableTypeHandler can resolve the row's TYPE_ name
Defensive patterns

Strategy: try-catch

Validate before calling

String typeName = getTypeNameFromRow(row);
Set<String> known = engineConfiguration.getVariableTypes().getVariableTypes().stream()
    .map(VariableType::getTypeName).collect(Collectors.toSet());
if (!known.contains(typeName)) {
    throw new IllegalStateException("Unregistered variable type in DB: " + typeName);
}

Try / catch

try {
    VariableType type = typeHandler.getResult(rs, "TYPE_");
} catch (FlowableException e) {
    if (e.getMessage().startsWith("unknown variable type name")) {
        log.error("Variable row has unregistered type; register it or migrate data", e);
        // skip row or fail the batch with a clear message
    } else {
        throw e;
    }
}

Prevention

When it happens

Trigger: Reading an ACT_RU_VARIABLE / ACT_HI_VARINST row whose TYPE_ value is not among registered types — e.g. the row was written by a different Flowable version or a custom variable type that is not registered in this deployment; a null-vs-typename mismatch in the custom-type registry.

Common situations: Rolling upgrades/downgrades where newer rows use types the older engine does not know; custom VariableType registered in one node of a cluster but not another; hand-edited or imported database data.

Understand the failure class

Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.

Related errors


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

Appendix: source

Thrown at modules/flowable-variable-service/src/main/java/org/flowable/variable/service/impl/db/IbatisVariableTypeHandler.java:43

import org.flowable.variable.api.types.VariableTypes;

/**
 * @author Dave Syer
 */
public class IbatisVariableTypeHandler implements TypeHandler<VariableType> {

    protected VariableTypes variableTypes;
    
    public IbatisVariableTypeHandler(VariableTypes variableTypes) {
        this.variableTypes = variableTypes;
    }

    @Override
    public VariableType getResult(ResultSet rs, String columnName) throws SQLException {
        String typeName = rs.getString(columnName);
        VariableType type = variableTypes.getVariableType(typeName);
        if (type == null && typeName != null) {
            throw new FlowableException("unknown variable type name " + typeName);
        }
        return type;
    }

    @Override
    public VariableType getResult(CallableStatement cs, int columnIndex) throws SQLException {
        String typeName = cs.getString(columnIndex);
        VariableType type = variableTypes.getVariableType(typeName);
        if (type == null) {
            throw new FlowableException("unknown variable type name " + typeName);
        }
        return type;
    }

    @Override
    public void setParameter(PreparedStatement ps, int i, VariableType parameter, JdbcType jdbcType) throws SQLException {
        String typeName = parameter.getTypeName();
        ps.setString(i, typeName);

View on GitHub (pinned to d6d39ce1c6)