prestodb/presto · error · PrestoException

DRUID_PUSHDOWN_UNSUPPORTED_EXPRESSION

DRUID_PUSHDOWN_UNSUPPORTED_EXPRESSION

Error message

Druid does not support lambda: ${lambda}

What it means

Druid pushdown of a projected expression encountered a RowExpression lambda (e.g. from higher-order functions like filter/transform/any_match). The Druid connector's expression converter has no translation for lambda definitions, so instead of silently degrading it throws to abort pushdown of this expression. The query should then fall back to non-pushdown execution, but the exception surfaces if pushdown failure is fatal or is being debugged.

Source

Thrown at presto-druid/src/main/java/com/facebook/presto/druid/DruidProjectExpressionConverter.java:71

        this.typeManager = requireNonNull(typeManager, "type manager");
        this.standardFunctionResolution = requireNonNull(standardFunctionResolution, "standardFunctionResolution is null");
    }

    @Override
    public DruidExpression visitVariableReference(
            VariableReferenceExpression reference,
            Map<VariableReferenceExpression, Selection> context)
    {
        Selection input = requireNonNull(context.get(reference), format("Input column %s does not exist in the input", reference));
        return new DruidExpression(input.getDefinition(), input.getOrigin());
    }

    @Override
    public DruidExpression visitLambda(
            LambdaDefinitionExpression lambda,
            Map<VariableReferenceExpression, Selection> context)
    {
        throw new PrestoException(DRUID_PUSHDOWN_UNSUPPORTED_EXPRESSION, "Druid does not support lambda: " + lambda);
    }

    protected boolean isImplicitCast(Type inputType, Type resultType)
    {
        if (typeManager.canCoerce(inputType, resultType)) {
            return true;
        }
        return resultType.getTypeSignature().getBase().equals(StandardTypes.TIMESTAMP) && TIME_EQUIVALENT_TYPES.contains(inputType.getTypeSignature().getBase());
    }

    private DruidExpression handleCast(
            CallExpression cast,
            Map<VariableReferenceExpression, Selection> context)
    {
        if (cast.getArguments().size() == 1) {
            RowExpression input = cast.getArguments().get(0);
            Type expectedType = cast.getType();
            if (isImplicitCast(input.getType(), expectedType)) {

View on GitHub (pinned to 55bb57d202)

Solutions

  1. Rewrite the query to avoid higher-order functions with lambdas in columns/predicates sent to Druid
  2. Compute the lambda expression outside the Druid pushdown (e.g. in an outer projection after the scan)
  3. Wrap the expression in a cast/context marker that prevents pushdown so it is evaluated in Presto instead

Example fix

// before
SELECT filter(a, x -> x > 10) FROM druid_table;
// after
SELECT a FROM druid_table; -- filter evaluated in Presto, not pushed to Druid
Defensive patterns

Strategy: try-catch

Validate before calling

// before relying on pushdown, scan the expression tree for lambdas
boolean hasLambda = rowExpression.accept(new Visitor<Void, Void>() {
    @Override public Void visitLambda(LambdaDefinitionExpression l, Void c) { throw new HasLambda(); }
}, null);

Type guard

boolean isPushableToDruid(RowExpression e) {
    return !(e instanceof LambdaDefinitionExpression);
}

Try / catch

try {
    converter.project(rowExpressions, context);
} catch (PrestoException e) {
    if (e.getErrorCode().equals(DRUID_PUSHDOWN_UNSUPPORTED_EXPRESSION.toErrorCode())) {
        // fall back: evaluate expression in Presto, not pushed to Druid
    } else { throw e; }
}

Prevention

When it happens

Trigger: Calling DruidProjectExpressionConverter.visitLambda via accept() on a LambdaDefinitionExpression while converting a project/aggregation expression for pushdown — i.e. the expression tree contains a higher-order-function lambda.

Common situations: Pushing down predicates or projections using higher-order functions (filter, all_match, reduce, transform) over Druid tables.

Related errors


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