prestodb/presto · error · PrestoException

AMBIGUOUS_FUNCTION_CALL

AMBIGUOUS_FUNCTION_CALL

Error message

Could not choose a best candidate operator. Explicit type casts must be added.
Candidates are:

What it means

FunctionSignatureMatcher.matchFunctionGeneric resolves a function call when several candidate overloads remain after deduplication and no single best candidate can be chosen. When multiple distinct applicable signatures tie, the matcher refuses to guess and throws AMBIGUOUS_FUNCTION_CALL, telling the developer to add explicit casts. The message says 'operator' but applies to generic function matching too.

Source

Thrown at presto-main-base/src/main/java/com/facebook/presto/metadata/FunctionSignatureMatcher.java:130

    {
        List<ApplicableFunction> applicableFunctions = identifyApplicableFunctions(candidates, actualParameters, false);
        if (applicableFunctions.isEmpty()) {
            return Optional.empty();
        }

        if (applicableFunctions.size() == 1) {
            return Optional.of(applicableFunctions.stream().collect(onlyElement()).getBoundSignature());
        }

        List<Signature> deduplicatedSignatures = applicableFunctions.stream()
                .map(applicableFunction -> applicableFunction.boundSignature)
                .distinct()
                .collect(toImmutableList());
        if (deduplicatedSignatures.size() == 1) {
            return Optional.of(deduplicatedSignatures.stream().collect(onlyElement()));
        }

        throw new PrestoException(AMBIGUOUS_FUNCTION_CALL, getErrorMessage(applicableFunctions));
    }

    private Optional<Signature> matchFunctionWithCoercion(Collection<? extends SqlFunction> candidates, List<TypeSignatureProvider> actualParameters)
    {
        return matchFunction(candidates, actualParameters, true);
    }

    private Optional<Signature> matchFunction(Collection<? extends SqlFunction> candidates, List<TypeSignatureProvider> parameters, boolean coercionAllowed)
    {
        List<ApplicableFunction> applicableFunctions = identifyApplicableFunctions(candidates, parameters, coercionAllowed);
        if (applicableFunctions.isEmpty()) {
            return Optional.empty();
        }

        if (coercionAllowed) {
            applicableFunctions = selectMostSpecificFunctions(applicableFunctions, parameters);
            checkState(!applicableFunctions.isEmpty(), "at least single function must be left");
        }

View on GitHub (pinned to 55bb57d202)

Solutions

  1. Add explicit CASTs on ambiguous arguments so exactly one overload matches, e.g. CAST(x AS DOUBLE)
  2. Inspect the 'Candidates are:' list in the message and pick the intended overload
  3. Rename/redefine overlapping UDF overloads in your plugin to remove the ambiguity
  4. Use typed literals (e.g. 1.0DOUBLE, DECIMAL '1.0') instead of untyped literals

Example fix

// before
SELECT my_max(1, 2.5); -- AMBIGUOUS_FUNCTION_CALL
// after
SELECT my_max(CAST(1 AS DOUBLE), 2.5);
Defensive patterns

Strategy: try-catch

Validate before calling

// Ensure arguments have unambiguous declared types before invoking overloaded functions
// e.g. avoid untyped literals/NULL: use CAST(expr AS <targetType>) in generated SQL

Try / catch

try { signature = matcher.matchFunctionGeneric(candidates, paramTypes); }
catch (PrestoException e) { if (AMBIGUOUS_FUNCTION_CALL.getCode() == e.getErrorCode()) { /* add casts and retry resolution */ } else throw e; }

Prevention

When it happens

Trigger: matchFunctionGeneric is given candidates where, after coercion and deduplication, more than one distinct signature applies equally — e.g. calling a function with argument types that two overloads can both accept with equal-cost coercions.

Common situations: Numeric literal or NULL argument that could coerce to multiple types (e.g. f(1) where f takes integer or double); overloaded UDFs with overlapping signatures; calls mixing types like decimal/double that both overloads accept after implicit coercion.

Related errors


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