prestodb/presto · error · PrestoException
ALREADY_EXISTS
ALREADY_EXISTS
Error message
TableFuncitonProcessorProvider already exists for connectorId %s. Overwriting is not supported.
What it means
Presto allows at most one TableFunctionProcessorProvider per connector. addTableFunctionProcessorProvider uses putIfAbsent and throws ALREADY_EXISTS if a provider was already registered for the given ConnectorId, because silently overwriting provider state is not supported.
Source
Thrown at presto-main-base/src/main/java/com/facebook/presto/metadata/FunctionAndTypeManager.java:741
}
if (isBuiltInWorkerFunctionHandle(functionHandle)) {
return builtInWorkerFunctionNamespaceManager.getScalarFunctionImplementation(functionHandle);
}
Optional<FunctionNamespaceManager<?>> functionNamespaceManager = getServingFunctionNamespaceManager(functionHandle.getCatalogSchemaName());
checkArgument(functionNamespaceManager.isPresent(), "Cannot find function namespace for '%s'", functionHandle.getCatalogSchemaName());
return functionNamespaceManager.get().getScalarFunctionImplementation(functionHandle);
}
public TableFunctionProcessorProvider getTableFunctionProcessorProvider(TableFunctionHandle tableFunctionHandle)
{
return tableFunctionProcessorProviderMap.get(tableFunctionHandle.getConnectorId()).apply(tableFunctionHandle.getFunctionHandle());
}
public void addTableFunctionProcessorProvider(ConnectorId connectorId, Function<ConnectorTableFunctionHandle, TableFunctionProcessorProvider> tableFunctionProcessorProvider)
{
if (tableFunctionProcessorProviderMap.putIfAbsent(connectorId, tableFunctionProcessorProvider) != null) {
throw new PrestoException(ALREADY_EXISTS,
format("TableFuncitonProcessorProvider already exists for connectorId %s. Overwriting is not supported.", connectorId.getCatalogName()));
}
}
public void removeTableFunctionProcessorProvider(ConnectorId connectorId)
{
tableFunctionProcessorProviderMap.remove(connectorId);
}
public AggregationFunctionImplementation getAggregateFunctionImplementation(FunctionHandle functionHandle)
{
if (isBuiltInPluginFunctionHandle(functionHandle)) {
return builtInPluginFunctionNamespaceManager.getAggregateFunctionImplementation(functionHandle, this);
}
if (isBuiltInWorkerFunctionHandle(functionHandle)) {
return builtInWorkerFunctionNamespaceManager.getAggregateFunctionImplementation(functionHandle, this);
}
View on GitHub (pinned to 55bb57d202)
Solutions
- Call removeTableFunctionProcessorProvider(connectorId) before adding the new provider
- Guard registration with a check so the provider is added only once per connectorId
- Fix the plugin lifecycle so registration happens exactly once (e.g. in class-load/init, not per-connection)
- If the old provider must be replaced, remove then re-add rather than expecting overwrite
Example fix
// before functionAndTypeManager.addTableFunctionProcessorProvider(connectorId, provider); functionAndTypeManager.addTableFunctionProcessorProvider(connectorId, newProvider); // throws ALREADY_EXISTS // after functionAndTypeManager.removeTableFunctionProcessorProvider(connectorId); functionAndTypeManager.addTableFunctionProcessorProvider(connectorId, newProvider);
Defensive patterns
Strategy: validation
Validate before calling
if (providerRegisteredFor(connectorId)) { skipOrRemoveFirst(); } Try / catch
try { fam.addTableFunctionProcessorProvider(connectorId, p); } catch (PrestoException e) { if (e.getErrorCode() == ALREADY_EXISTS) { fam.removeTableFunctionProcessorProvider(connectorId); fam.addTableFunctionProcessorProvider(connectorId, p); } } Prevention
- Track registration state per connectorId before adding
- Always pair add with remove in lifecycle callbacks
- In tests, build a fresh FunctionAndTypeManager per case instead of re-adding
When it happens
Trigger: Calling FunctionAndTypeManager.addTableFunctionProcessorProvider(connectorId, provider) twice for the same connector without calling removeTableFunctionProcessorProvider in between; typically a plugin or connector trying to re-register during reconfiguration or test setup.
Common situations: Connector plugin lifecycle bugs where the connector is activated twice; unit tests that rebuild the FunctionAndTypeManager or re-add providers against the same instance; hot-swapping a connector's table function provider without removal.
Related errors
- ARROW_INTERNAL_ERROR
- NOT_SUPPORTED
- INVALID_SESSION_PROPERTY
- FUNCTION_NOT_FOUND
- FUNCTION_IMPLEMENTATION_ERROR
AI-assisted analysis of prestodb/presto@55bb57d202 (2026-09-04).
Data as JSON: /api/errors/44666c0335bf7d77.
Report an issue: GitHub.