{"record":{"id":"403bb73132c1a3d2","repo":"prestodb/presto","slug":"not-supported-403bb7","errorCode":"NOT_SUPPORTED","errorMessage":"Invoking a dynamically registered function in SQL function body is not supported","messagePattern":"Invoking a dynamically registered function in SQL function body is not supported","errorType":"error_code","errorClass":"PrestoException","httpStatus":null,"severity":"error","filePath":"presto-main-base/src/main/java/com/facebook/presto/execution/CreateFunctionTask.java","lineNumber":98,"sourceCode":"\n    @Override\n    public String explain(CreateFunction statement, List<Expression> parameters)\n    {\n        return format(\"CREATE %sFUNCTION %s\", statement.isTemporary() ? \"TEMPORARY \" : \"\", statement.getFunctionName());\n    }\n\n    @Override\n    public ListenableFuture<?> execute(CreateFunction statement, TransactionManager transactionManager, Metadata metadata, AccessControl accessControl, QueryStateMachine stateMachine, List<Expression> parameters, String query)\n    {\n        Map<NodeRef<com.facebook.presto.sql.tree.Parameter>, Expression> parameterLookup = parameterExtractor(statement, parameters);\n        Session session = stateMachine.getSession();\n        Analyzer analyzer = new Analyzer(session, metadata, sqlParser, accessControl, Optional.empty(), parameters, parameterLookup, stateMachine.getWarningCollector(), query, new ViewDefinitionReferences());\n        Analysis analysis = analyzer.analyzeSemantic(statement, false);\n        checkAccessPermissions(analysis.getAccessControlReferences(), analysis.getViewDefinitionReferences(), query, session.getPreparedStatements(), session.getIdentity(), accessControl, session.getAccessControlContext());\n\n        if (analysis.getFunctionHandles().values().stream()\n                .anyMatch(SqlFunctionHandle.class::isInstance)) {\n            throw new PrestoException(NOT_SUPPORTED, \"Invoking a dynamically registered function in SQL function body is not supported\");\n        }\n\n        SqlInvokedFunction function = createSqlInvokedFunction(statement, metadata, analysis);\n        if (statement.isTemporary()) {\n            stateMachine.addSessionFunction(new SqlFunctionId(function.getSignature().getName(), function.getSignature().getArgumentTypes()), function);\n        }\n        else {\n            metadata.getFunctionAndTypeManager().createFunction(function, statement.isReplace());\n        }\n\n        return immediateFuture(null);\n    }\n\n    @Override\n    public void queryPermissionCheck(AccessControl accessControl, Identity identity, AccessControlContext context, String query, Map<String, String> preparedStatements, Map<QualifiedObjectName, ViewDefinition> viewDefinitions, Map<QualifiedObjectName, MaterializedViewDefinition> materializedViewDefinitions) {}\n\n    private SqlInvokedFunction createSqlInvokedFunction(CreateFunction statement, Metadata metadata, Analysis analysis)\n    {","sourceCodeStart":80,"sourceCodeEnd":116,"githubUrl":"https://github.com/prestodb/presto/blob/55bb57d202de3b926896fa966c2c4a44c779634e/presto-main-base/src/main/java/com/facebook/presto/execution/CreateFunctionTask.java#L80-L116","documentation":"CREATE FUNCTION bodies may only call functions resolvable at creation time. If semantic analysis of the function body yields handles that are instances of SqlFunctionHandle — i.e. dynamically (session-level) registered SQL functions — CreateFunctionTask throws PrestoException NOT_SUPPORTED.","triggerScenarios":"Defining a SQL function whose body calls a function registered dynamically in the session (e.g. via a prior temporary CREATE FUNCTION in the same session); nesting dynamic function references inside new function definitions.","commonSituations":"Scripted sessions that register helper functions and then build more functions on top; session-scoped temporary functions referenced from persistent catalog functions; migration scripts chaining function definitions.","solutions":["Remove the call to the dynamically registered function from the function body","Register the dependency as a persistent catalog function so the body resolves a static handle","Inline the dependent function's logic into the new function body","Restructure to define the dependency first as a permanent function in the same catalog"],"exampleFix":"// before\nCREATE FUNCTION my.lib.f(x bigint) RETURNS bigint AS $$ SELECT my.session_helper(x) + 1 $$; -- session_helper is dynamic\n// after\nCREATE FUNCTION my.lib.helper(x bigint) RETURNS bigint AS $$ ... $$; -- permanent\nCREATE FUNCTION my.lib.f(x bigint) RETURNS bigint AS $$ SELECT my.lib.helper(x) + 1 $$;","handlingStrategy":"validation","validationCode":"// ensure function bodies only reference persistent functions\nSet<String> dynamicFunctions = sessionFunctions.keySet();\nfor (String callee : referencedFunctions(body)) {\n    if (dynamicFunctions.contains(callee)) {\n        throw new IllegalStateException(\"Body references dynamic function: \" + callee);\n    }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Register helper functions as persistent catalog functions, not session-temporary","Never build permanent functions on top of session-scoped temporary functions","Review function definition scripts for cross-session dependencies"],"tags":["not-supported","udf","sql-functions"],"backgroundTag":"dynamic-function-unsupported","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"}