prestodb/presto · error · PrestoException
ALREADY_EXISTS
ALREADY_EXISTS
Error message
Session function %s has already been defined
What it means
Thrown by QueryStateMachine.addSessionFunction when a session function with the same SqlFunctionId signature is already registered for the query session. Presto sessions allow only one definition per function signature; re-registering the same signature is treated as a conflict. The check consults both the session's existing functions and the set of functions added during this query.
Source
Thrown at presto-main-base/src/main/java/com/facebook/presto/execution/QueryStateMachine.java:744
}
public void removePreparedStatement(String key)
{
requireNonNull(key, "key is null");
if (!session.getPreparedStatements().containsKey(key)) {
throw new PrestoException(NOT_FOUND, "Prepared statement not found: " + key);
}
deallocatedPreparedStatements.add(key);
}
public void addSessionFunction(SqlFunctionId signature, SqlInvokedFunction function)
{
requireNonNull(signature, "signature is null");
requireNonNull(function, "function is null");
if (session.getSessionFunctions().containsKey(signature) || addedSessionFunctions.putIfAbsent(signature, function) != null) {
throw new PrestoException(ALREADY_EXISTS, format("Session function %s has already been defined", signature));
}
}
public void removeSessionFunction(SqlFunctionId signature, boolean suppressNotFoundException)
{
requireNonNull(signature, "signature is null");
if (!session.getSessionFunctions().containsKey(signature)) {
if (!suppressNotFoundException) {
throw new PrestoException(NOT_FOUND, format("Session function %s not found", signature.getFunctionName()));
}
}
else {
removedSessionFunctions.add(signature);
}
}
public void setStartedTransactionId(TransactionId startedTransactionId)View on GitHub (pinned to 55bb57d202)
Solutions
- Drop the existing session function first via removeSessionFunction (or DROP FUNCTION in SQL) before re-adding it
- Use a different function signature (distinct parameter types) if the intent is an overload
- Check session.getSessionFunctions().containsKey(signature) before calling addSessionFunction
- Guard against concurrent registration by ensuring a single thread owns session function management
Example fix
// before
stateMachine.addSessionFunction(signature, function); // throws if already defined
// after
if (!session.getSessionFunctions().containsKey(signature)) {
stateMachine.addSessionFunction(signature, function);
} else {
stateMachine.removeSessionFunction(signature, false);
stateMachine.addSessionFunction(signature, function);
} Defensive patterns
Strategy: validation
Validate before calling
if (session.getSessionFunctions().containsKey(signature)) {
// already defined — skip or drop-then-add
return;
}
stateMachine.addSessionFunction(signature, function); Try / catch
try {
stateMachine.addSessionFunction(signature, function);
} catch (PrestoException e) {
if (e.getErrorCode().getCode() == StandardErrorCode.ALREADY_EXISTS.getCode()) {
stateMachine.removeSessionFunction(signature, true);
stateMachine.addSessionFunction(signature, function);
} else { throw e; }
} Prevention
- Always pair ADD FUNCTION with a prior DROP FUNCTION in session scripts
- Track registered signatures in client code to avoid re-registration on retries
- Never share one session across threads that both register functions
When it happens
Trigger: Calling addSessionFunction with a SqlFunctionId already present in session.getSessionFunctions() or already added via addedSessionFunctions (putIfAbsent returns non-null). Typically two ADD FUNCTION statements for the same signature in one session, or a concurrent registration race.
Common situations: Re-running an ADD FUNCTION SQL statement without DROP FUNCTION first; client retry re-sending the same session-function registration; two threads sharing a session registering the same function concurrently.
Related errors
AI-assisted analysis of prestodb/presto@55bb57d202 (2026-09-04).
Data as JSON: /api/errors/58a178537cdda5b2.
Report an issue: GitHub.