{"record":{"id":"7c81c0a797eb7661","repo":"flowable/flowable-engine","slug":"jdbc-requires-that-the-jdbctype-must-be-specified","errorCode":null,"errorMessage":"JDBC requires that the JdbcType must be specified for all nullable parameters.","messagePattern":"JDBC requires that the JdbcType must be specified for all nullable parameters\\.","errorType":"exception","errorClass":"TypeException","httpStatus":null,"severity":"error","filePath":"modules/flowable-engine-common/src/main/java/org/flowable/common/engine/impl/db/FlowableStringTypeHandler.java","lineNumber":25,"sourceCode":"import java.sql.Types;\n\nimport org.apache.ibatis.type.BaseTypeHandler;\nimport org.apache.ibatis.type.JdbcType;\nimport org.apache.ibatis.type.TypeException;\n\npublic class FlowableStringTypeHandler extends BaseTypeHandler<String> {\n    \n    protected boolean useDefaultJdbcType;\n    \n    public FlowableStringTypeHandler(boolean useDefaultJdbcType) {\n        this.useDefaultJdbcType = useDefaultJdbcType;\n    }\n    \n    @Override\n    public void setParameter(PreparedStatement ps, int i, String parameter, JdbcType jdbcType) throws SQLException {\n        if (parameter == null) {\n            if (jdbcType == null) {\n                throw new TypeException(\"JDBC requires that the JdbcType must be specified for all nullable parameters.\");\n            }\n            try {\n                if (useDefaultJdbcType) {\n                    JdbcType finalJdbcType = null;\n                    if (jdbcType.equals(JdbcType.NVARCHAR)) {\n                        finalJdbcType = JdbcType.VARCHAR;\n                    } else {\n                        finalJdbcType = jdbcType;\n                    }\n                    ps.setNull(i,  finalJdbcType.TYPE_CODE);\n                    \n                } else {\n                    ps.setNull(i, Types.NULL);\n                }\n            } catch (SQLException e) {\n                throw new TypeException(\"Error setting null for parameter #\" + i + \" with JdbcType \" + jdbcType + \" . \"\n                      + \"Try setting a different JdbcType for this parameter or a different jdbcTypeForNull configuration property. \"\n                      + \"Cause: \" + e, e);","sourceCodeStart":7,"sourceCodeEnd":43,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable-engine-common/src/main/java/org/flowable/common/engine/impl/db/FlowableStringTypeHandler.java#L7-L43","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Add an explicit jdbcType to nullable parameter mappings, e.g. #{name,jdbcType=VARCHAR}.","Set MyBatis configuration property jdbcTypeForNull=VARCHAR so nulls always get a type.","Ensure variables set into the engine are non-null where the mapping has no jdbcType.","Verify the JDBC driver supports the configured JdbcType for null binding."],"exampleFix":"// before (mapper XML)\n#{description}\n// after\n#{description,jdbcType=VARCHAR}","handlingStrategy":"validation","validationCode":"if (value == null) ensureMapperDeclaresJdbcType(\"name\", \"VARCHAR\"); // or set jdbcTypeForNull=VARCHAR globally","typeGuard":"boolean needsJdbcType(Object v) { return v == null; } // if true, mapping must declare jdbcType","tryCatchPattern":"catch (TypeException e) { if (e.getMessage().contains(\"JdbcType must be specified\")) { /* add jdbcType to mapping or set jdbcTypeForNull */ } throw e; }","preventionTips":["Always add jdbcType=VARCHAR to nullable #{...} mappings.","Set MyBatis jdbcTypeForNull=VARCHAR.","Avoid passing null engine variables where mappings lack jdbcType."],"tags":["mybatis","jdbc","null","database","flowable"],"backgroundTag":"null-argument","analyzedSha":"d6d39ce1c69ff244f2d9dc6af756a9b95e865586","analyzedAt":"2026-09-11T06:41:19.413Z","contentChangedAt":"2026-09-11T06:41:19.413Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}