{"record":{"id":"f4750464869ca05a","repo":"mybatis/mybatis-3","slug":"dynamic-content-is-not-allowed-when-using-raw-lang","errorCode":null,"errorMessage":"Dynamic content is not allowed when using RAW language","messagePattern":"Dynamic content is not allowed when using RAW language","errorType":"exception","errorClass":"BuilderException","httpStatus":null,"severity":"error","filePath":"src/main/java/org/apache/ibatis/scripting/defaults/RawLanguageDriver.java","lineNumber":52,"sourceCode":"\n  @Override\n  public SqlSource createSqlSource(Configuration configuration, XNode script, Class<?> parameterType) {\n    SqlSource source = super.createSqlSource(configuration, script, parameterType);\n    checkIsNotDynamic(source);\n    return source;\n  }\n\n  @Override\n  public SqlSource createSqlSource(Configuration configuration, String script, Class<?> parameterType,\n      ParamNameResolver paramNameResolver) {\n    SqlSource source = super.createSqlSource(configuration, script, parameterType, paramNameResolver);\n    checkIsNotDynamic(source);\n    return source;\n  }\n\n  private void checkIsNotDynamic(SqlSource source) {\n    if (!RawSqlSource.class.equals(source.getClass())) {\n      throw new BuilderException(\"Dynamic content is not allowed when using RAW language\");\n    }\n  }\n\n}\n","sourceCodeStart":34,"sourceCodeEnd":57,"githubUrl":"https://github.com/mybatis/mybatis-3/blob/008069adb1b089579b5dcba87ee591908b263274/src/main/java/org/apache/ibatis/scripting/defaults/RawLanguageDriver.java#L34-L57","documentation":"RawLanguageDriver forces every statement to be a static, pre-compilable RawSqlSource. After building a SqlSource it checks the concrete class; anything other than RawSqlSource (i.e. DynamicSqlSource) means the script contained dynamic constructs, so a BuilderException is thrown at startup. Dynamic tags (${} substitution, <if>, <where>, <foreach>, etc.) are incompatible with the RAW driver by design.","triggerScenarios":"Setting defaultLanguageDriverClass (or a statement's lang attribute) to RawLanguageDriver while the mapper still contains ${...}, <if>, <choose>, <foreach>, <set>, <where>, <bind>, or <include> fragments that expand to dynamic SQL.","commonSituations":"Adopting RawLanguageDriver for startup-time performance/static SQL verification on an existing mapper suite; mixing drivers and forgetting to clean dynamic constructs out of some statements; copy-pasting dynamic SQL into a RAW-driver statement.","solutions":["Replace dynamic constructs with static SQL: use #{} parameters, split conditional variants into separate statements","Switch those statements back to the default XMLLanguageDriver (remove lang=\"raw\" or per-statement driver override)","If you only need runtime-value binding (not SQL text changes), #{} placeholders are fine under RAW — convert ${} to #{} where possible"],"exampleFix":"<!-- before (RawLanguageDriver) -->\n<select id=\"find\" lang=\"raw\" ...>SELECT * FROM t WHERE status = #{status}<if test=\"name != null\"> AND name = #{name}</if></select>\n\n<!-- after -->\n<select id=\"find\" ...>SELECT * FROM t WHERE status = #{status} AND name = #{name}</select>","handlingStrategy":"validation","validationCode":"// at bootstrap, validate each statement against the RAW driver\ntry {\n  rawDriver.createSqlSource(configuration, script, parameterType, paramNameResolver);\n} catch (BuilderException e) {\n  // statement contains dynamic content; assign it the default XML driver instead\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Audit mappers for ${}, <if>, <foreach>, <where>, <set>, <choose>, <bind> before enabling RawLanguageDriver","Enable RAW per statement (lang=\"raw\") incrementally rather than globally","Keep static-SQL statements in separate mapper files when using RAW"],"tags":["sql-building","language-driver","configuration","dynamic-sql","mybatis"],"backgroundTag":null,"analyzedSha":"008069adb1b089579b5dcba87ee591908b263274","analyzedAt":"2026-08-14T13:07:10.264Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}