{"record":{"id":"f2db327ea0813567","repo":"flowable/flowable-engine","slug":"unknown-variable-type-name","errorCode":null,"errorMessage":"unknown variable type name ","messagePattern":"unknown variable type name ","errorType":"exception","errorClass":"FlowableException","httpStatus":null,"severity":"critical","filePath":"modules/flowable-variable-service/src/main/java/org/flowable/variable/service/impl/db/IbatisVariableTypeHandler.java","lineNumber":43,"sourceCode":"import org.flowable.variable.api.types.VariableTypes;\n\n/**\n * @author Dave Syer\n */\npublic class IbatisVariableTypeHandler implements TypeHandler<VariableType> {\n\n    protected VariableTypes variableTypes;\n    \n    public IbatisVariableTypeHandler(VariableTypes variableTypes) {\n        this.variableTypes = variableTypes;\n    }\n\n    @Override\n    public VariableType getResult(ResultSet rs, String columnName) throws SQLException {\n        String typeName = rs.getString(columnName);\n        VariableType type = variableTypes.getVariableType(typeName);\n        if (type == null && typeName != null) {\n            throw new FlowableException(\"unknown variable type name \" + typeName);\n        }\n        return type;\n    }\n\n    @Override\n    public VariableType getResult(CallableStatement cs, int columnIndex) throws SQLException {\n        String typeName = cs.getString(columnIndex);\n        VariableType type = variableTypes.getVariableType(typeName);\n        if (type == null) {\n            throw new FlowableException(\"unknown variable type name \" + typeName);\n        }\n        return type;\n    }\n\n    @Override\n    public void setParameter(PreparedStatement ps, int i, VariableType parameter, JdbcType jdbcType) throws SQLException {\n        String typeName = parameter.getTypeName();\n        ps.setString(i, typeName);","sourceCodeStart":25,"sourceCodeEnd":61,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable-variable-service/src/main/java/org/flowable/variable/service/impl/db/IbatisVariableTypeHandler.java#L25-L61","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Register the missing VariableType in the engine configuration (customPostVariableTypes / variableTypes) so getVariableType finds it","Align Flowable versions across all nodes writing/reading the variable tables","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)"],"exampleFix":"// before (type missing at startup)\nProcessEngineConfiguration cfg = ProcessEngineConfiguration\n    .createProcessEngineConfigurationFromResource(\"flowable.cfg.xml\");\n// after\ncfg.setCustomPostVariableTypes(\n    Collections.singletonList(new MyCustomVariableType()));\n// so IbatisVariableTypeHandler can resolve the row's TYPE_ name","handlingStrategy":"try-catch","validationCode":"String typeName = getTypeNameFromRow(row);\nSet<String> known = engineConfiguration.getVariableTypes().getVariableTypes().stream()\n    .map(VariableType::getTypeName).collect(Collectors.toSet());\nif (!known.contains(typeName)) {\n    throw new IllegalStateException(\"Unregistered variable type in DB: \" + typeName);\n}","typeGuard":null,"tryCatchPattern":"try {\n    VariableType type = typeHandler.getResult(rs, \"TYPE_\");\n} catch (FlowableException e) {\n    if (e.getMessage().startsWith(\"unknown variable type name\")) {\n        log.error(\"Variable row has unregistered type; register it or migrate data\", e);\n        // skip row or fail the batch with a clear message\n    } else {\n        throw e;\n    }\n}","preventionTips":["Register all custom VariableTypes in every engine configuration/cluster node","Keep Flowable versions aligned across services sharing the same database","Audit TYPE_ column values in ACT_RU_VARIABLE/ACT_HI_VARINST after upgrades or data imports","Test variable round-trips (persist + query) after any type-registry change"],"tags":["database","variable-types","deserialization","version-mismatch","flowable"],"backgroundTag":"invalid-enum-value","analyzedSha":"d6d39ce1c69ff244f2d9dc6af756a9b95e865586","analyzedAt":"2026-09-11T06:41:19.413Z","contentChangedAt":"2026-09-11T06:41:19.413Z","schemaVersion":2},"datasetVersion":"2026-09-18T11:17:12.947Z"}