flowable/flowable-engine · error · ActivitiException

unknown variable type name

Error message

unknown variable type name <typeName>

What it means

IbatisVariableTypeHandler.getResult reads the TYPE_ column of a variable row and looks it up among registered VariableTypes. When the stored type name is non-null but no registered type matches, Flowable throws because it cannot deserialize the variable value. This typically means the row was written by an engine with different variable type handlers.

Solutions

  1. Re-register the missing VariableType in the process engine configuration (customTypes / preBPMNParseHandlers on VariableTypes)
  2. Identify the offending TYPE_ value via SELECT DISTINCT TYPE_ on the variable tables and map it to a supported type
  3. Restore the engine version that wrote the data, or migrate the variable rows to supported types
  4. If the variable is obsolete, clean up the rows in a controlled migration

Example fix

// before
ProcessEngineConfiguration cfg = ProcessEngineConfiguration
    .createProcessEngineConfigurationFromResourceDefault();
// after
cfg.setCustomPostVariableTypes(new CustomStringType("custom-json")); // re-add handler for stored TYPE_ 'custom-json'
Defensive patterns

Strategy: try-catch

Validate before calling

Set<String> known = variableTypes.keySet == null ? null : null; // check via:
// SELECT DISTINCT TYPE_ FROM ACT_RU_VARIABLE
// and confirm each value resolves through engineConfig.getVariableTypes().getVariableType(type) != null

Type guard

boolean isKnownVariableType(ProcessEngineConfiguration cfg, String typeName) {
  return typeName != null && cfg.getVariableTypes().getVariableType(typeName) != null;
}

Try / catch

try {
  Map<String, Object> vars = taskService.getVariables(taskId);
} catch (ActivitiException e) {
  if (e.getMessage().startsWith("unknown variable type name")) {
    logger.error("Variable row references an unregistered type; register the VariableType or migrate rows", e);
  }
  throw e;
}

Prevention

When it happens

Trigger: Reading process/execution/task variables via the API or engine queries when a row in ACT_RU_VARIABLE / ACT_HI_VARINSTALL has a TYPE_ value not present in the current VariableTypes registry (e.g. custom type removed, engine downgraded, JSON type missing).

Common situations: Upgrading/downgrading engines with different variable types, removing a custom VariableType from the config while old rows still reference it, or history rows written by a newer engine version.

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/bb291233c25427f8. Report an issue: GitHub.

Appendix: source

Thrown at modules/flowable5-engine/src/main/java/org/activiti/engine/impl/db/IbatisVariableTypeHandler.java:40

import org.activiti.engine.impl.context.Context;
import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.TypeHandler;
import org.flowable.variable.api.types.VariableType;
import org.flowable.variable.api.types.VariableTypes;

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

    protected VariableTypes variableTypes;

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

    @Override
    public VariableType getResult(CallableStatement cs, int columnIndex) throws SQLException {
        String typeName = cs.getString(columnIndex);
        VariableType type = getVariableTypes().getVariableType(typeName);
        if (type == null) {
            throw new ActivitiException("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)