flowable/flowable-engine · error · TypeException

JDBC requires that the JdbcType must be specified for all nu

Error message

JDBC requires that the JdbcType must be specified for all nullable parameters.

What it means

A MyBatis TypeException thrown by FlowableStringTypeHandler.setParameter when binding a null String parameter whose JdbcType is unspecified. Some JDBC drivers cannot bind NULL without a type hint, so Flowable's type handler refuses to proceed rather than let the driver fail opaquely.

Source

Thrown at modules/flowable-engine-common/src/main/java/org/flowable/common/engine/impl/db/FlowableStringTypeHandler.java:25

import java.sql.Types;

import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.TypeException;

public class FlowableStringTypeHandler extends BaseTypeHandler<String> {
    
    protected boolean useDefaultJdbcType;
    
    public FlowableStringTypeHandler(boolean useDefaultJdbcType) {
        this.useDefaultJdbcType = useDefaultJdbcType;
    }
    
    @Override
    public void setParameter(PreparedStatement ps, int i, String parameter, JdbcType jdbcType) throws SQLException {
        if (parameter == null) {
            if (jdbcType == null) {
                throw new TypeException("JDBC requires that the JdbcType must be specified for all nullable parameters.");
            }
            try {
                if (useDefaultJdbcType) {
                    JdbcType finalJdbcType = null;
                    if (jdbcType.equals(JdbcType.NVARCHAR)) {
                        finalJdbcType = JdbcType.VARCHAR;
                    } else {
                        finalJdbcType = jdbcType;
                    }
                    ps.setNull(i,  finalJdbcType.TYPE_CODE);
                    
                } else {
                    ps.setNull(i, Types.NULL);
                }
            } catch (SQLException e) {
                throw new TypeException("Error setting null for parameter #" + i + " with JdbcType " + jdbcType + " . "
                      + "Try setting a different JdbcType for this parameter or a different jdbcTypeForNull configuration property. "
                      + "Cause: " + e, e);

View on GitHub (pinned to d6d39ce1c6)

Solutions

  1. Add an explicit jdbcType to nullable parameter mappings, e.g. #{name,jdbcType=VARCHAR}.
  2. Set MyBatis configuration property jdbcTypeForNull=VARCHAR so nulls always get a type.
  3. Ensure variables set into the engine are non-null where the mapping has no jdbcType.
  4. Verify the JDBC driver supports the configured JdbcType for null binding.

Example fix

// before (mapper XML)
#{description}
// after
#{description,jdbcType=VARCHAR}
Defensive patterns

Strategy: validation

Validate before calling

if (value == null) ensureMapperDeclaresJdbcType("name", "VARCHAR"); // or set jdbcTypeForNull=VARCHAR globally

Type guard

boolean needsJdbcType(Object v) { return v == null; } // if true, mapping must declare jdbcType

Try / catch

catch (TypeException e) { if (e.getMessage().contains("JdbcType must be specified")) { /* add jdbcType to mapping or set jdbcTypeForNull */ } throw e; }

Prevention

When it happens

Trigger: Executing a mapped statement that passes a null String into a prepared-statement parameter while the mapping/MyBatis global jdbcTypeForNull yields jdbcType == null; custom SQL/XML mappings omitting jdbcType=... on a nullable parameter.

Common situations: Custom MyBatis mapper XML with #{prop} and no jdbcType attribute where the value is null; overriding jdbcTypeForNull to something invalid; reusing Flowable's type handler in custom persistence code.

Related errors


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