{"record":{"id":"1651e382a4f35ea5","repo":"prestodb/presto","slug":"function-not-found-1651e3","errorCode":"FUNCTION_NOT_FOUND","errorMessage":"Dependent function implementation (%s) with convention (%s) is not available","messagePattern":"Dependent function implementation \\((.+?)\\) with convention \\((.+?)\\) is not available","errorType":"error_code","errorClass":"PrestoException","httpStatus":null,"severity":"error","filePath":"presto-main-base/src/main/java/com/facebook/presto/metadata/FunctionInvokerProvider.java","lineNumber":58,"sourceCode":"public class FunctionInvokerProvider\n{\n    private final FunctionAndTypeManager functionAndTypeManager;\n\n    public FunctionInvokerProvider(FunctionAndTypeManager functionAndTypeManager)\n    {\n        this.functionAndTypeManager = functionAndTypeManager;\n    }\n\n    public FunctionInvoker createFunctionInvoker(FunctionHandle functionHandle, Optional<InvocationConvention> invocationConvention)\n    {\n        JavaScalarFunctionImplementation functionImplementation = functionAndTypeManager.getJavaScalarFunctionImplementation(functionHandle);\n        for (ScalarFunctionImplementationChoice choice : getAllScalarFunctionImplementationChoices(functionImplementation)) {\n            if (checkChoice(choice.getArgumentProperties(), choice.isNullable(), choice.hasProperties(), invocationConvention)) {\n                return new FunctionInvoker(choice.getMethodHandle());\n            }\n        }\n        checkState(invocationConvention.isPresent());\n        throw new PrestoException(FUNCTION_NOT_FOUND, format(\"Dependent function implementation (%s) with convention (%s) is not available\", functionHandle, invocationConvention.toString()));\n    }\n\n    @VisibleForTesting\n    static boolean checkChoice(List<ArgumentProperty> definitionArgumentProperties, boolean definitionReturnsNullable, boolean definitionHasSession, Optional<InvocationConvention> invocationConvention)\n    {\n        for (int i = 0; i < definitionArgumentProperties.size(); i++) {\n            InvocationArgumentConvention invocationArgumentConvention = invocationConvention.get().getArgumentConvention(i);\n            NullConvention nullConvention = definitionArgumentProperties.get(i).getNullConvention();\n            // return false because function types do not have a null convention\n            if (definitionArgumentProperties.get(i).getArgumentType() == FUNCTION_TYPE) {\n                if (invocationArgumentConvention != InvocationArgumentConvention.FUNCTION) {\n                    return false;\n                }\n                // Support can be added when this becomes necessary\n                throw new UnsupportedOperationException(\"Invocation convention for function type is not supported\");\n            }\n            if (nullConvention == RETURN_NULL_ON_NULL && invocationArgumentConvention != InvocationArgumentConvention.NEVER_NULL) {\n                return false;","sourceCodeStart":40,"sourceCodeEnd":76,"githubUrl":"https://github.com/prestodb/presto/blob/55bb57d202de3b926896fa966c2c4a44c779634e/presto-main-base/src/main/java/com/facebook/presto/metadata/FunctionInvokerProvider.java#L40-L76","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Update the scalar function implementation to provide an implementation choice matching the requested InvocationConvention (e.g. add a nullable or convention-capable variant)","Check the @SqlNullable / @SqlType annotations and ArgumentProperties on the UDF — align them with how it is invoked","If it's a third-party plugin, upgrade it to a build compiled against the current SPI","File/inspect with the function handle from the message to see which choice is missing"],"exampleFix":"// before\n@SqlType(StandardTypes.BIGINT)\npublic long myUdf(long x) {...} // only one choice, no nullable/convention variant\n// after\n@SqlNullable\n@SqlType(StandardTypes.BIGINT)\npublic Long myUdf(@Nullable Long x) {...} // supports nullable arguments","handlingStrategy":"try-catch","validationCode":"// Verify the UDF declares implementations matching the required convention before binding\nboolean hasChoice = getAllScalarFunctionImplementationChoices(impl).stream()\n    .anyMatch(c -> checkChoice(c.getArgumentProperties(), c.isNullable(), c.hasProperties(), convention));","typeGuard":null,"tryCatchPattern":"try { invoker = invokerProvider.createFunctionInvoker(impl, convention); }\ncatch (PrestoException e) { if (FUNCTION_NOT_FOUND.getCode() == e.getErrorCode()) { /* use a default/interpreted fallback invoker */ } else throw e; }","preventionTips":["Annotate UDFs with @SqlNullable and provide nullable/convention variants when args may be null","Compile custom function plugins against the exact Presto SPI version in use","Test UDF invocation paths (nullable, session, convention) in plugin unit tests"],"tags":["presto","scalar-function","invocation-convention"],"backgroundTag":"function-not-found","analyzedSha":"55bb57d202de3b926896fa966c2c4a44c779634e","analyzedAt":"2026-09-04T12:50:26.162Z","contentChangedAt":"2026-09-04T12:50:26.162Z","schemaVersion":2},"datasetVersion":"2026-09-11T21:17:09.523Z"}