apache/druid · critical · ISE
set to 'false', but has been removed, see for details for…
Error message
%s set to 'false', but has been removed, see %s for details for how to migrate to SQL compliant behavior
What it means
The three-value-logic toggle druid.sql.expressionProcessor/three-value-logic config has been removed; Druid now always uses three-valued logic when SQL-compliant null handling is on. StartupInjectorBuilder.validate() throws this ISE at startup if the property is set to 'false' to prevent silently reverting to legacy non-3VL semantics.
Solutions
- Remove the property or set it to 'true' in runtime properties
- Migrate queries per the linked ANSI SQL null migration doc to get expected results under three-valued logic
- Audit dashboards/scheduled queries that relied on legacy boolean NULL semantics and update comparisons (e.g. use IS NOT DISTINCT FROM or explicit NULL checks)
Example fix
// before <removed-3vl-property>=false // after # property removed (3VL always enabled)
Defensive patterns
Strategy: validation
Validate before calling
String v = props.getProperty("<three-value-logic-property>");
if ("false".equalsIgnoreCase(v)) throw new IllegalStateException("3VL toggle removed; must not be 'false'"); Try / catch
try { injector = StartupInjectorBuilder.build(); } catch (ISE e) { if (e.getMessage().contains("set to 'false', but has been removed")) log.error("Remove the legacy 3VL flag; see migration doc"); throw e; } Prevention
- Remove obsolete toggles from config templates when the upgrade plan is drafted
- Verify query results that depended on legacy boolean-NULL semantics in a staging cluster
- Automate a config audit that flags keys absent from current docs
When it happens
Trigger: validate() computes no3vl = !Boolean.parseBoolean(properties.getProperty(THREE_VALUE_LOGIC_CONFIG_STRING, "true")); the property being explicitly 'false' triggers the throw before the injector is built.
Common situations: Clusters upgraded from legacy versions where 3VL was opt-in; ops teams disabling 3VL to reproduce old query results; stale config files carried across upgrades.
Related errors
- set to 'true', but has been removed, see for details for…
- At least one of the druid.enablePlaintextPort or…
- Cannot return double for Null Value
- Cannot return long for Null Value
- Cannot return primitive float for Null Value
AI-assisted analysis of apache/druid@9b90983fd2 (2026-09-07).
Data as JSON: /api/errors/bd2db295dd99f598.
Report an issue: GitHub.
Appendix: source
Thrown at processing/src/main/java/org/apache/druid/guice/StartupInjectorBuilder.java:154
{
final boolean defaultValueMode = Boolean.parseBoolean(
properties.getProperty(NULL_HANDLING_CONFIG_STRING, "false")
);
if (defaultValueMode) {
final String docsLink = StringUtils.format("https://druid.apache.org/docs/%s/release-info/migr-ansi-sql-null", getVersionString());
throw new ISE(
"%s set to 'true', but has been removed, see %s for details for how to migrate to SQL compliant behavior",
NULL_HANDLING_CONFIG_STRING,
docsLink
);
}
final boolean no3vl = !Boolean.parseBoolean(
properties.getProperty(THREE_VALUE_LOGIC_CONFIG_STRING, "true")
);
if (no3vl) {
final String docsLink = StringUtils.format("https://druid.apache.org/docs/%s/release-info/migr-ansi-sql-null", getVersionString());
throw new ISE(
"%s set to 'false', but has been removed, see %s for details for how to migrate to SQL compliant behavior",
THREE_VALUE_LOGIC_CONFIG_STRING,
docsLink
);
}
final boolean nonStrictExpressions = !Boolean.parseBoolean(
properties.getProperty(ExpressionProcessingConfig.NULL_HANDLING_LEGACY_LOGICAL_OPS_STRING, "true")
);
if (nonStrictExpressions) {
final String docsLink = StringUtils.format("https://druid.apache.org/docs/%s/release-info/migr-ansi-sql-null", getVersionString());
throw new ISE(
"%s set to 'false', but has been removed, see %s for details for how to migrate to SQL compliant behavior",
ExpressionProcessingConfig.NULL_HANDLING_LEGACY_LOGICAL_OPS_STRING,
docsLink
);
}
View on GitHub (pinned to 9b90983fd2)