prestodb/presto · error · PrestoException

DATATYPE_MISMATCH

DATATYPE_MISMATCH

Error message

Expected row filter for '%s' to be of type BOOLEAN, but was %s

What it means

A row filter acts as a boolean predicate appended to queries against the table, so its analyzed type must be BOOLEAN (or coercible to BOOLEAN). If the expression's type is neither BOOLEAN nor coercible, Presto throws DATATYPE_MISMATCH with this message.

Source

Thrown at presto-main-base/src/main/java/com/facebook/presto/sql/analyzer/StatementAnalyzer.java:5374

                        analysis,
                        expression,
                        warningCollector);
            }
            catch (PrestoException e) {
                throw new PrestoException(e::getErrorCode, format("Invalid row filter for '%s: %s'", name, e.getMessage()), e);
            }
            finally {
                analysis.unregisterTableForRowFiltering(name, currentIdentity);
            }

            verifyNoAggregateWindowOrGroupingFunctions(analysis.getFunctionHandles(), functionAndTypeResolver, expression, format("Row filter for '%s'", name));

            analysis.recordSubqueries(expression, expressionAnalysis);

            Type actualType = expressionAnalysis.getType(expression);
            if (!actualType.equals(BOOLEAN)) {
                if (!metadata.getFunctionAndTypeManager().canCoerce(actualType, BOOLEAN)) {
                    throw new PrestoException(DATATYPE_MISMATCH, format("Expected row filter for '%s' to be of type BOOLEAN, but was %s", name, actualType), null);
                }

                analysis.addCoercion(expression, BOOLEAN, false);
            }

            analysis.addRowFilter(table, expression);
        }

        private void analyzeColumnMask(String currentIdentity, Table table, QualifiedObjectName tableName, ColumnMetadata columnMetadata, Scope scope, ViewExpression mask)
        {
            String column = columnMetadata.getName();
            if (analysis.hasColumnMask(tableName, column, currentIdentity)) {
                throw new PrestoException(INVALID_COLUMN_MASK, format("Column mask for '%s.%s' is recursive", tableName, column), null);
            }

            Expression expression;
            try {
                expression = sqlParser.createExpression(mask.getExpression(), createParsingOptions(session));

View on GitHub (pinned to 55bb57d202)

Solutions

  1. Wrap the expression in an explicit boolean comparison, e.g. `status = 'ACTIVE'`
  2. Cast the result: `CAST(col AS boolean)` if the cast is valid
  3. Fix the policy store so the registered ViewExpression is a predicate, not a value

Example fix

// before
"is_active_user_id"
// after
"is_active = true"
Defensive patterns

Strategy: validation

Validate before calling

// Check the filter analyzes to a BOOLEAN (or coercible) type before installing:
Type actual = expressionAnalysis.getType(expression);
if (!actual.equals(BOOLEAN) && !metadata.getFunctionAndTypeManager().canCoerce(actual, BOOLEAN)) {
    throw new IllegalArgumentException("Row filter must be boolean, got: " + actual);
}

Type guard

boolean isBooleanFilter(Type t, FunctionAndTypeManager ftm) {
    return t.equals(BOOLEAN) || ftm.canCoerce(t, BOOLEAN);
}

Try / catch

try { session.execute("SELECT * FROM " + table); }
catch (PrestoException e) {
    if ("DATATYPE_MISMATCH".equals(e.getErrorCode().getName()) && e.getMessage().contains("row filter")) {
        throw new PolicyConfigurationException("Row filter must be a boolean predicate", e);
    } else { throw e; }
}

Prevention

When it happens

Trigger: A row filter expression like `user_id` (integer) or `status` (varchar) without a comparison; thrown in analyzeRowFilter after ExpressionAnalysis when canCoerce(actualType, BOOLEAN) is false.

Common situations: Defining a filter as a bare column reference assuming implicit truthiness; forgetting `= TRUE` / `IS TRUE`; filters returning int codes instead of boolean; copy-pasting projection expressions into filter policies.

Related errors


AI-assisted analysis of prestodb/presto@55bb57d202 (2026-09-04). Data as JSON: /api/errors/fc1a0d673807ed6c. Report an issue: GitHub.