prestodb/presto · error · PrestoException

FUNCTION_NOT_FOUND

FUNCTION_NOT_FOUND

Error message

Dependent function implementation (%s) with convention (%s) is not available

What it means

FunctionInvokerProvider builds the invoker for a scalar function handle given the caller's InvocationConvention (how arguments/return are passed, nullability expectations). If none of the function's compiled implementation choices supports the requested convention, it throws FUNCTION_NOT_FOUND. This means the function exists, but not with an implementation compatible with how the caller wants to invoke it.

Source

Thrown at presto-main-base/src/main/java/com/facebook/presto/metadata/FunctionInvokerProvider.java:58

public class FunctionInvokerProvider
{
    private final FunctionAndTypeManager functionAndTypeManager;

    public FunctionInvokerProvider(FunctionAndTypeManager functionAndTypeManager)
    {
        this.functionAndTypeManager = functionAndTypeManager;
    }

    public FunctionInvoker createFunctionInvoker(FunctionHandle functionHandle, Optional<InvocationConvention> invocationConvention)
    {
        JavaScalarFunctionImplementation functionImplementation = functionAndTypeManager.getJavaScalarFunctionImplementation(functionHandle);
        for (ScalarFunctionImplementationChoice choice : getAllScalarFunctionImplementationChoices(functionImplementation)) {
            if (checkChoice(choice.getArgumentProperties(), choice.isNullable(), choice.hasProperties(), invocationConvention)) {
                return new FunctionInvoker(choice.getMethodHandle());
            }
        }
        checkState(invocationConvention.isPresent());
        throw new PrestoException(FUNCTION_NOT_FOUND, format("Dependent function implementation (%s) with convention (%s) is not available", functionHandle, invocationConvention.toString()));
    }

    @VisibleForTesting
    static boolean checkChoice(List<ArgumentProperty> definitionArgumentProperties, boolean definitionReturnsNullable, boolean definitionHasSession, Optional<InvocationConvention> invocationConvention)
    {
        for (int i = 0; i < definitionArgumentProperties.size(); i++) {
            InvocationArgumentConvention invocationArgumentConvention = invocationConvention.get().getArgumentConvention(i);
            NullConvention nullConvention = definitionArgumentProperties.get(i).getNullConvention();
            // return false because function types do not have a null convention
            if (definitionArgumentProperties.get(i).getArgumentType() == FUNCTION_TYPE) {
                if (invocationArgumentConvention != InvocationArgumentConvention.FUNCTION) {
                    return false;
                }
                // Support can be added when this becomes necessary
                throw new UnsupportedOperationException("Invocation convention for function type is not supported");
            }
            if (nullConvention == RETURN_NULL_ON_NULL && invocationArgumentConvention != InvocationArgumentConvention.NEVER_NULL) {
                return false;

View on GitHub (pinned to 55bb57d202)

Solutions

  1. Update the scalar function implementation to provide an implementation choice matching the requested InvocationConvention (e.g. add a nullable or convention-capable variant)
  2. Check the @SqlNullable / @SqlType annotations and ArgumentProperties on the UDF — align them with how it is invoked
  3. If it's a third-party plugin, upgrade it to a build compiled against the current SPI
  4. File/inspect with the function handle from the message to see which choice is missing

Example fix

// before
@SqlType(StandardTypes.BIGINT)
public long myUdf(long x) {...} // only one choice, no nullable/convention variant
// after
@SqlNullable
@SqlType(StandardTypes.BIGINT)
public Long myUdf(@Nullable Long x) {...} // supports nullable arguments
Defensive patterns

Strategy: try-catch

Validate before calling

// Verify the UDF declares implementations matching the required convention before binding
boolean hasChoice = getAllScalarFunctionImplementationChoices(impl).stream()
    .anyMatch(c -> checkChoice(c.getArgumentProperties(), c.isNullable(), c.hasProperties(), convention));

Try / catch

try { invoker = invokerProvider.createFunctionInvoker(impl, convention); }
catch (PrestoException e) { if (FUNCTION_NOT_FOUND.getCode() == e.getErrorCode()) { /* use a default/interpreted fallback invoker */ } else throw e; }

Prevention

When it happens

Trigger: createFunctionInvoker is called with an InvocationConvention that no ScalarFunctionImplementationChoice satisfies — e.g. a caller requests a nullable-return or convention-passing variant the function's implementation doesn't provide.

Common situations: Custom scalar functions lacking the implementation variants (e.g. no nullable-return instance) that the execution engine requests; engine/connector convention mismatches after adding new argument properties (session, convention) to a UDF; partially written custom function plugins.

Related errors


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