YunaiV/yudao-cloud · error · UnexpectedLiquibaseException
Unknown boolean value: {}
Error message
Unknown boolean value: {} What it means
Liquibase BooleanType.objectToSqlValue fails to recognize the given value as a boolean. String values are matched against 'true'/'false', '1'/'0', "b'0'"/'f' (case-insensitive) and the database's native true/false literals; anything else reaches the final else branch and throws UnexpectedLiquibaseException.
Source
Thrown at sql/dm/flowable-patch/src/main/java/liquibase/datatype/core/BooleanType.java:85
}
String returnValue;
if (value instanceof String) {
value = ((String) value).replaceAll("'", "");
if ("true".equals(((String) value).toLowerCase(Locale.US)) || "1".equals(value) || "b'1'".equals(((String) value).toLowerCase(Locale.US)) || "t".equals(((String) value).toLowerCase(Locale.US)) || ((String) value).toLowerCase(Locale.US).equals(this.getTrueBooleanValue(database).toLowerCase(Locale.US))) {
returnValue = this.getTrueBooleanValue(database);
} else if ("false".equals(((String) value).toLowerCase(Locale.US)) || "0".equals(value) || "b'0'".equals(
((String) value).toLowerCase(Locale.US)) || "f".equals(((String) value).toLowerCase(Locale.US)) || ((String) value).toLowerCase(Locale.US).equals(this.getFalseBooleanValue(database).toLowerCase(Locale.US))) {
returnValue = this.getFalseBooleanValue(database);
} else if (database instanceof PostgresDatabase && Pattern.matches("b?([01])\\1*(::bit|::\"bit\")?", (String) value)) {
returnValue = "b'"
+ value.toString()
.replace("b", "")
.replace("\"", "")
.replace("::it", "")
+ "'::\"bit\"";
} else {
throw new UnexpectedLiquibaseException("Unknown boolean value: " + value);
}
} else if (value instanceof Long) {
if (Long.valueOf(1).equals(value)) {
returnValue = this.getTrueBooleanValue(database);
} else {
returnValue = this.getFalseBooleanValue(database);
}
} else if (value instanceof Number) {
if (value.equals(1) || "1".equals(value.toString()) || "1.0".equals(value.toString())) {
returnValue = this.getTrueBooleanValue(database);
} else {
returnValue = this.getFalseBooleanValue(database);
}
} else if (value instanceof DatabaseFunction) {
return value.toString();
} else if (value instanceof Boolean) {
if (((Boolean) value)) {
returnValue = this.getTrueBooleanValue(database);View on GitHub (pinned to 477be9dd49)
Solutions
- Use a canonical boolean string in the changeset: 'true'/'false', '1'/'0', or exactly the value the target database's getTrueBooleanValue()/getFalseBooleanValue() returns.
- Remove extra quotes/whitespace — pass true, not 'true' with embedded quotes.
- If the value is computed SQL, move it to defaultValueComputed instead of defaultValue.
- For database-specific literals, set the value in a changeset property conditioned per-database (context/dbms attribute).
Example fix
<!-- before --> <column name="active" type="boolean" defaultValue="yes"/> <!-- after --> <column name="active" type="boolean" defaultValue="true"/>
Defensive patterns
Strategy: validation
Validate before calling
private static final Pattern OK = Pattern.compile("(?i)^(true|false|1|0|b'[01]'|t|f)$");
String v = String.valueOf(defaultValue).trim();
if (!OK.matcher(v).matches()) throw new IllegalArgumentException("Bad boolean literal: " + v); Type guard
boolean isLiquibaseBoolean(Object v) {
return v instanceof Boolean || v instanceof Number
|| (v instanceof String s && s.matches("(?i)(true|false|1|0|b'[01]'|t|f)"));
} Try / catch
try { value = BooleanType.objectToSqlValue(raw, db); }
catch (UnexpectedLiquibaseException e) {
if (e.getMessage().startsWith("Unknown boolean value")) value = raw == null ? null : String.valueOf(raw);
else throw e;
} Prevention
- Normalize boolean defaults to 'true'/'false' or '1'/'0' at the edge of changelog generation
- Lint changelog XML for defaultValue attributes outside the accepted literal set in CI
When it happens
Trigger: A changeset column default value or <constraints> boolean value passes a string that is not in the accepted set, e.g. defaultValue="yes", defaultValue="Y", defaultValueComputed misused for a plain string, or a dialect-specific literal (e.g. "t"' or "TRUE()") that the current database's getTrueBooleanValue() does not return.
Common situations: Porting a changelog written for one database (MySQL '1'/'0', PostgreSQL bit strings) to another (DM/Oracle expecting 'TRUE'/'FALSE' or 1/0); XML changelogs where defaultValueComputed is used instead of defaultValue; locale-specific or quoted literals like "'true'" (extra quotes).
Related errors
AI-assisted analysis of YunaiV/yudao-cloud@477be9dd49 (2026-08-14).
Data as JSON: /api/errors/fd78f94d75d280d7.
Report an issue: GitHub.