prestodb/presto · error · PrestoException

FUNCTION_NOT_FOUND

FUNCTION_NOT_FOUND

Error message

Invalid function name: 

What it means

TableFunctionRegistry.toPath resolves a QualifiedName into a list of catalog/schema-qualified function names for table function lookup. A qualified name with more than three parts is not a valid function path, so it throws FUNCTION_NOT_FOUND with the offending name. Valid paths are 1–3 parts (function, schema.function, catalog.schema.function).

Source

Thrown at presto-main-base/src/main/java/com/facebook/presto/metadata/TableFunctionRegistry.java:84

            builder.put(
                    new SchemaFunctionName(
                            function.getSchema().toLowerCase(ENGLISH),
                            function.getName().toLowerCase(ENGLISH)),
                    new TableFunctionMetadata(catalogName, function));
        }
        tableFunctions.putIfAbsent(catalogName, builder.buildOrThrow());
    }

    public void removeTableFunctions(ConnectorId catalogName)
    {
        tableFunctions.remove(catalogName);
    }

    public static List<CatalogSchemaFunctionName> toPath(Session session, QualifiedName name)
    {
        List<String> parts = name.getParts();
        if (parts.size() > 3) {
            throw new PrestoException(StandardErrorCode.FUNCTION_NOT_FOUND, "Invalid function name: " + name);
        }
        if (parts.size() == 3) {
            return ImmutableList.of(new CatalogSchemaFunctionName(parts.get(0), parts.get(1), parts.get(2)));
        }

        if (parts.size() == 2) {
            String currentCatalog = session.getCatalog()
                    .orElseThrow(() -> new PrestoException(SESSION_CATALOG_NOT_SET, "Session default catalog must be set to resolve a partial function name: " + name));
            return ImmutableList.of(new CatalogSchemaFunctionName(currentCatalog, parts.get(0), parts.get(1)));
        }

        ImmutableList.Builder<CatalogSchemaFunctionName> names = ImmutableList.builder();

        String currentCatalog = session.getCatalog()
                .orElseThrow(() -> new SemanticException(CATALOG_NOT_SPECIFIED, "Catalog must be specified when session catalog is not set"));
        String currentSchema = session.getSchema()
                .orElseThrow(() -> new SemanticException(SCHEMA_NOT_SPECIFIED, "Schema must be specified when session schema is not set"));

View on GitHub (pinned to 55bb57d202)

Solutions

  1. Reduce the function name to at most catalog.schema.function
  2. Use schema.function or plain function name and rely on session catalog/schema
  3. Fix SQL generators/templates that prepend an extra catalog qualifier

Example fix

// before
SELECT * FROM TABLE(mycluster.mycatalog.my_schema.my_func(x));
// after
SELECT * FROM TABLE(my_schema.my_func(x));
Defensive patterns

Strategy: validation

Validate before calling

QualifiedName name = ...;
if (name.getParts().size() > 3) {
    throw new IllegalArgumentException("Function name must have at most 3 parts: " + name);
}

Type guard

boolean isValidFunctionName(QualifiedName name) {
    return name.getParts().size() >= 1 && name.getParts().size() <= 3;
}

Try / catch

try {
    List<CatalogSchemaFunctionName> path = TableFunctionRegistry.toPath(session, name);
} catch (PrestoException e) {
    if (e.getErrorCode().getCode() == StandardErrorCode.FUNCTION_NOT_FOUND.toErrorCode().getCode()) {
        // retry with trimmed qualification: drop leading catalog parts
    }
    throw e;
}

Prevention

When it happens

Trigger: Invoking a table function with a name having 4+ dot-separated parts, e.g. SELECT * FROM TABLE(a.b.c.d(...)) or an over-qualified name in a saved query.

Common situations: Copy-pasted fully-qualified names including cluster/catalog prefix beyond what Presto allows; generated SQL that over-qualifies; typos adding an extra qualifier.

Related errors


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