prestodb/presto · error · PrestoException

NOT_SUPPORTED

NOT_SUPPORTED

Error message

External function in join filter is not supported: %s

What it means

Presto's planner refuses to plan join queries whose join filter contains a call to an external (connector/plugin-provided) function. External functions cannot be safely evaluated in the distributed join-filter context, so CheckUnsupportedExternalFunctions walks the plan and rejects any JoinNode whose filter expression contains such a call.

Source

Thrown at presto-main-base/src/main/java/com/facebook/presto/sql/planner/sanity/CheckUnsupportedExternalFunctions.java:81

        @Override
        public Void visitAggregation(AggregationNode node, Void context)
        {
            checkState(
                    node.getAggregations().values().stream()
                            .noneMatch(
                                    aggregation -> aggregation.getFilter().isPresent() ||
                                            aggregation.getCall().accept(externalCallExpressionChecker, null)),
                    "Expect aggregation to be local");

            node.getSource().accept(this, context);
            return null;
        }

        @Override
        public Void visitJoin(JoinNode node, Void context)
        {
            if (node.getFilter().isPresent() && node.getFilter().get().accept(externalCallExpressionChecker, null)) {
                throw new PrestoException(NOT_SUPPORTED, format("External function in join filter is not supported: %s", node.getFilter().get()));
            }

            node.getSources().forEach(child -> child.accept(this, context));
            return null;
        }

        @Override
        public Void visitApply(ApplyNode node, Void context)
        {
            throw new IllegalStateException("Do not expect ApplyNode");
        }

        @Override
        public Void visitLateralJoin(LateralJoinNode node, Void context)
        {
            throw new IllegalStateException("Do not expect ApplyNode");
        }
    }

View on GitHub (pinned to 55bb57d202)

Solutions

  1. Move the external function call out of the join filter into a subquery/CTE that computes it before the join (e.g. precompute in a SELECT, then join on the result).
  2. Replace the external function with an equivalent built-in Presto function if one exists.
  3. If the function must be used in the join predicate, check whether the connector offers a native (non-external) variant or pushdown of the predicate.
  4. As a last resort, restructure as a lateral/cross join plus WHERE if the planner supports it for that function.

Example fix

// before
SELECT * FROM a JOIN b ON a.id = b.id AND my_ext_func(a.ts) > 10
// after
WITH pre AS (SELECT *, my_ext_func(ts) AS f FROM a)
SELECT * FROM pre JOIN b ON pre.id = b.id AND pre.f > 10
Defensive patterns

Strategy: validation

Validate before calling

// Inspect join filters for external functions before submitting
boolean hasExternalCallInJoin(PlanNode joinNode, Metadata metadata) {
    return joinNode.getFilter()
        .map(f -> f.accept(new ExternalCallExpressionChecker(metadata), null))
        .orElse(false);
}
if (hasExternalCallInJoin(node, metadata)) { /* rewrite query to precompute */ }

Prevention

When it happens

Trigger: Running a query with an explicit join condition (e.g. `... JOIN t ON a.x = b.y AND ext_func(a.z)`) where `ext_func` is registered by a connector as an external function, so the filter expression passed the externalCallExpressionChecker during plan sanity validation in visitJoin.

Common situations: Queries mixing built-in and connector-provided UDFs in JOIN ON clauses; migrations after a connector adds external function support; users assuming external functions behave like ordinary scalar functions everywhere.

Understand the failure class

Background: Presto NOT_SUPPORTED error: what "not supported" means and how to fix it — this error's family across 3 libraries.

Related errors


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