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
- Use CREATE FUNCTION ... OR REPLACE (or pass replace=true to createFunction).
- Drop or clear the existing function before re-creating it (dropFunction is unsupported here, so use a fresh manager instance in tests).
- 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
- Use CREATE OR REPLACE for idempotent function setup scripts.
- Check existing functions before creating in shared test fixtures.
- Isolate each test with its own InMemoryFunctionNamespaceManager instance.
- Make setup methods idempotent rather than additive.
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.