{"record":{"id":"44666c0335bf7d77","repo":"prestodb/presto","slug":"already-exists-44666c","errorCode":"ALREADY_EXISTS","errorMessage":"TableFuncitonProcessorProvider already exists for connectorId %s. Overwriting is not supported.","messagePattern":"TableFuncitonProcessorProvider already exists for connectorId (.+?)\\. Overwriting is not supported\\.","errorType":"error_code","errorClass":"PrestoException","httpStatus":null,"severity":"error","filePath":"presto-main-base/src/main/java/com/facebook/presto/metadata/FunctionAndTypeManager.java","lineNumber":741,"sourceCode":"        }\n        if (isBuiltInWorkerFunctionHandle(functionHandle)) {\n            return builtInWorkerFunctionNamespaceManager.getScalarFunctionImplementation(functionHandle);\n        }\n\n        Optional<FunctionNamespaceManager<?>> functionNamespaceManager = getServingFunctionNamespaceManager(functionHandle.getCatalogSchemaName());\n        checkArgument(functionNamespaceManager.isPresent(), \"Cannot find function namespace for '%s'\", functionHandle.getCatalogSchemaName());\n        return functionNamespaceManager.get().getScalarFunctionImplementation(functionHandle);\n    }\n\n    public TableFunctionProcessorProvider getTableFunctionProcessorProvider(TableFunctionHandle tableFunctionHandle)\n    {\n        return tableFunctionProcessorProviderMap.get(tableFunctionHandle.getConnectorId()).apply(tableFunctionHandle.getFunctionHandle());\n    }\n\n    public void addTableFunctionProcessorProvider(ConnectorId connectorId, Function<ConnectorTableFunctionHandle, TableFunctionProcessorProvider> tableFunctionProcessorProvider)\n    {\n        if (tableFunctionProcessorProviderMap.putIfAbsent(connectorId, tableFunctionProcessorProvider) != null) {\n            throw new PrestoException(ALREADY_EXISTS,\n                    format(\"TableFuncitonProcessorProvider already exists for connectorId %s. Overwriting is not supported.\", connectorId.getCatalogName()));\n        }\n    }\n\n    public void removeTableFunctionProcessorProvider(ConnectorId connectorId)\n    {\n        tableFunctionProcessorProviderMap.remove(connectorId);\n    }\n\n    public AggregationFunctionImplementation getAggregateFunctionImplementation(FunctionHandle functionHandle)\n    {\n        if (isBuiltInPluginFunctionHandle(functionHandle)) {\n            return builtInPluginFunctionNamespaceManager.getAggregateFunctionImplementation(functionHandle, this);\n        }\n        if (isBuiltInWorkerFunctionHandle(functionHandle)) {\n            return builtInWorkerFunctionNamespaceManager.getAggregateFunctionImplementation(functionHandle, this);\n        }\n","sourceCodeStart":723,"sourceCodeEnd":759,"githubUrl":"https://github.com/prestodb/presto/blob/55bb57d202de3b926896fa966c2c4a44c779634e/presto-main-base/src/main/java/com/facebook/presto/metadata/FunctionAndTypeManager.java#L723-L759","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\nfunctionAndTypeManager.addTableFunctionProcessorProvider(connectorId, provider);\nfunctionAndTypeManager.addTableFunctionProcessorProvider(connectorId, newProvider); // throws ALREADY_EXISTS\n// after\nfunctionAndTypeManager.removeTableFunctionProcessorProvider(connectorId);\nfunctionAndTypeManager.addTableFunctionProcessorProvider(connectorId, newProvider);","handlingStrategy":"validation","validationCode":"if (providerRegisteredFor(connectorId)) { skipOrRemoveFirst(); }","typeGuard":null,"tryCatchPattern":"try { fam.addTableFunctionProcessorProvider(connectorId, p); } catch (PrestoException e) { if (e.getErrorCode() == ALREADY_EXISTS) { fam.removeTableFunctionProcessorProvider(connectorId); fam.addTableFunctionProcessorProvider(connectorId, p); } }","preventionTips":["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"],"tags":["presto","connector","table-function","duplicate-registration"],"backgroundTag":"duplicate-registration","analyzedSha":"55bb57d202de3b926896fa966c2c4a44c779634e","analyzedAt":"2026-09-04T12:50:26.162Z","contentChangedAt":"2026-09-04T12:50:26.162Z","schemaVersion":2},"datasetVersion":"2026-09-11T21:17:09.523Z"}