{"record":{"id":"acae6d7c4446faf4","repo":"mybatis/mybatis-3","slug":"unknown-datasource-property-propertyname","errorCode":null,"errorMessage":"Unknown DataSource property: ${propertyName}","messagePattern":"Unknown DataSource property: (.+?)","errorType":"exception","errorClass":"DataSourceException","httpStatus":null,"severity":"error","filePath":"src/main/java/org/apache/ibatis/datasource/unpooled/UnpooledDataSourceFactory.java","lineNumber":55,"sourceCode":"  public UnpooledDataSourceFactory() {\n    this.dataSource = new UnpooledDataSource();\n  }\n\n  @Override\n  public void setProperties(Properties properties) {\n    Properties driverProperties = new Properties();\n    MetaObject metaDataSource = SystemMetaObject.forObject(dataSource);\n    for (Object key : properties.keySet()) {\n      String propertyName = (String) key;\n      if (propertyName.startsWith(DRIVER_PROPERTY_PREFIX)) {\n        String value = properties.getProperty(propertyName);\n        driverProperties.setProperty(propertyName.substring(DRIVER_PROPERTY_PREFIX_LENGTH), value);\n      } else if (metaDataSource.hasSetter(propertyName)) {\n        String value = (String) properties.get(propertyName);\n        Object convertedValue = convertValue(metaDataSource, propertyName, value);\n        metaDataSource.setValue(propertyName, convertedValue);\n      } else {\n        throw new DataSourceException(\"Unknown DataSource property: \" + propertyName);\n      }\n    }\n    if (driverProperties.size() > 0) {\n      metaDataSource.setValue(\"driverProperties\", driverProperties);\n    }\n  }\n\n  @Override\n  public DataSource getDataSource() {\n    return dataSource;\n  }\n\n  private Object convertValue(MetaObject metaDataSource, String propertyName, String value) {\n    Object convertedValue = value;\n    Class<?> targetType = metaDataSource.getSetterType(propertyName);\n    if (targetType == Integer.class || targetType == int.class) {\n      convertedValue = Integer.valueOf(value);\n    } else if (targetType == Long.class || targetType == long.class) {","sourceCodeStart":37,"sourceCodeEnd":73,"githubUrl":"https://github.com/mybatis/mybatis-3/blob/008069adb1b089579b5dcba87ee591908b263274/src/main/java/org/apache/ibatis/datasource/unpooled/UnpooledDataSourceFactory.java#L37-L73","documentation":"UnpooledDataSourceFactory.setProperties() maps each configuration property onto the UnpooledDataSource bean via reflection. Properties starting with 'driver.' are collected as raw driver properties; any other property must have a corresponding setter on UnpooledDataSource (driver, url, username, password, autoCommit, defaultAutoCommit, defaultTransactionIsolationLevel, defaultNetworkTimeout, driverClassLoader, driverProperties, loginTimeout). Anything else throws DataSourceException 'Unknown DataSource property: <name>'.","triggerScenarios":"Typing a property in the UNPOOLED dataSource config that has no setter (e.g., 'user' instead of 'username', 'jdbcUrl' instead of 'url', pool settings like 'maximumPoolSize' that only exist on POOLED or external pools); passing HikariCP/DBCP option names to the built-in factories; misspelled property names in mybatis-config.xml or a Properties object passed to a DataSourceFactory.","commonSituations":"Copy-pasting datasource config from HikariCP/DBCP/Tomcat JDBC examples into MyBatis' built-in factories; assuming 'user' works (it is 'username'); putting JDBC URL parameters as top-level properties instead of inside the url value or under driver. prefix.","solutions":["Fix or remove the offending property — the message names it exactly","Use only supported setters: driver, url, username, password, autoCommit, defaultTransactionIsolationLevel, defaultNetworkTimeout, loginTimeout","Driver-specific connection settings must go through the 'driver.' prefix (e.g., driver.encoding=UTF8) which becomes java.util.Properties passed to DriverManager","If you need richer options (pool size, cachePrepStmts...), switch to type=\"POOLED\" pool.* properties or plug in an external pool via a custom DataSourceFactory"],"exampleFix":"<!-- before -->\n<dataSource type=\"UNPOOLED\">\n  <property name=\"jdbcUrl\" value=\"jdbc:mysql://db/app\"/> <!-- wrong: use 'url' -->\n  <property name=\"user\" value=\"app\"/>                    <!-- wrong: use 'username' -->\n</dataSource>\n\n<!-- after -->\n<dataSource type=\"UNPOOLED\">\n  <property name=\"url\" value=\"jdbc:mysql://db/app\"/>\n  <property name=\"username\" value=\"app\"/>\n  <property name=\"driver.characterEncoding\" value=\"utf8\"/>\n</dataSource>","handlingStrategy":"validation","validationCode":"// Validate config keys against the known UNPOOLED setter set before passing to MyBatis:\nSet<String> allowed = Set.of(\"driver\",\"url\",\"username\",\"password\",\"autoCommit\",\n    \"defaultAutoCommit\",\"defaultTransactionIsolationLevel\",\"defaultNetworkTimeout\",\n    \"driverClassLoader\",\"driverProperties\",\"loginTimeout\");\nfor (String k : props.stringPropertyNames()) {\n  if (!k.startsWith(\"driver.\") && !allowed.contains(k))\n    throw new IllegalArgumentException(\"Unknown DataSource property: \" + k);\n}","typeGuard":null,"tryCatchPattern":"try {\n  factory.setProperties(props);\n} catch (DataSourceException e) {\n  if (e.getMessage().startsWith(\"Unknown DataSource property:\")) {\n    // message names the bad key: fix or move it under the 'driver.' prefix\n  } else throw e;\n}","preventionTips":["Use 'username'/'url' (not 'user'/'jdbcUrl') with MyBatis built-in DataSource factories","Put driver-specific options under the driver. prefix","Fail configuration at startup in a test that builds the DataSource"],"tags":["mybatis","configuration","datasource","typo","startup"],"backgroundTag":null,"analyzedSha":"008069adb1b089579b5dcba87ee591908b263274","analyzedAt":"2026-08-14T13:07:10.264Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}