prestodb/presto · error · PrestoException

GENERIC_USER_ERROR

GENERIC_USER_ERROR

Error message

Function '%s' already exists

What it means

InMemoryFunctionNamespaceManager.createFunction throws GENERIC_USER_ERROR when a function with the same SqlFunctionId already exists and replace=false. The in-memory manager keys functions by id; creating a duplicate without replace would silently shadow the existing definition, so it is rejected.

Source

Thrown at presto-function-namespace-managers-common/src/main/java/com/facebook/presto/functionNamespace/testing/InMemoryFunctionNamespaceManager.java:72

    public InMemoryFunctionNamespaceManager(String catalogName, SqlFunctionExecutors sqlFunctionExecutors, SqlInvokedFunctionNamespaceManagerConfig config)
    {
        super(catalogName, sqlFunctionExecutors, config);
    }

    @Override
    public void setBlockEncodingSerde(BlockEncodingSerde blockEncodingSerde)
    {
        // Do not need to do anything here since InMemoryFunctionNamespaceManager cannot execute functions
    }

    @Override
    public synchronized void createFunction(SqlInvokedFunction function, boolean replace)
    {
        checkFunctionLanguageSupported(function);
        SqlFunctionId functionId = function.getFunctionId();
        if (!replace && latestFunctions.containsKey(function.getFunctionId())) {
            throw new PrestoException(GENERIC_USER_ERROR, format("Function '%s' already exists", functionId.getId()));
        }

        SqlInvokedFunction replacedFunction = latestFunctions.get(functionId);
        long version = 1;
        if (replacedFunction != null) {
            version = parseLong(replacedFunction.getRequiredVersion()) + 1;
        }
        latestFunctions.put(functionId, function.withVersion(String.valueOf(version)));
    }

    @Override
    public void alterFunction(QualifiedObjectName functionName, Optional<List<TypeSignature>> parameterTypes, AlterRoutineCharacteristics alterRoutineCharacteristics)
    {
        throw new PrestoException(NOT_SUPPORTED, "Alter Function is not supported in InMemoryFunctionNamespaceManager");
    }

    @Override
    public synchronized void dropFunction(QualifiedObjectName functionName, Optional<List<TypeSignature>> parameterTypes, boolean exists)

View on GitHub (pinned to 55bb57d202)

Solutions

  1. Use CREATE FUNCTION ... OR REPLACE (or pass replace=true to createFunction).
  2. Drop or clear the existing function before re-creating it (dropFunction is unsupported here, so use a fresh manager instance in tests).
  3. Guard creation with a existence check via listFunctions/getFunction before calling createFunction.

Example fix

// before
CREATE FUNCTION test_ns.double_it(x BIGINT) RETURNS BIGINT RETURN x * 2;
-- second run fails
// after
CREATE OR REPLACE FUNCTION test_ns.double_it(x BIGINT) RETURNS BIGINT RETURN x * 2;
Defensive patterns

Strategy: validation

Validate before calling

boolean exists = manager.listFunctions(functionName).stream()
        .anyMatch(f -> f.getFunctionId().equals(function.getFunctionId()));
// only call createFunction(..., false) when !exists, otherwise use replace=true

Try / catch

try {
    manager.createFunction(function, false);
} catch (PrestoException e) {
    if (e.getMessage().contains("already exists")) {
        manager.createFunction(function, true); // OR REPLACE
    }
}

Prevention

When it happens

Trigger: Calling createFunction(function, replace=false) when latestFunctions already contains function.getFunctionId(); running the same CREATE FUNCTION twice without OR REPLACE; test setup re-registering a helper function.

Common situations: Repeated test setup against the shared in-memory manager; forgetting the 'OR REPLACE' clause; idempotency issues where a script reruns CREATE FUNCTION statements.

Related errors


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