prestodb/presto · error · IllegalArgumentException
Access control '%s' is already registered
Error message
Access control '%s' is already registered
What it means
AccessControlManager.addSystemAccessControlFactory registers SystemAccessControlFactory instances by name in a map using putIfAbsent. If a factory with the same getName() is already registered, it throws IllegalArgumentException — the manager never allows two system access control plugins under one name.
Source
Thrown at presto-main-base/src/main/java/com/facebook/presto/security/AccessControlManager.java:108
private final CounterStat authorizationFail = new CounterStat();
private StatsRecordingSystemAccessControl.Stats detailedStats = new StatsRecordingSystemAccessControl.Stats();
@Inject
public AccessControlManager(TransactionManager transactionManager)
{
this.transactionManager = requireNonNull(transactionManager, "transactionManager is null");
addSystemAccessControlFactory(new AllowAllSystemAccessControl.Factory());
addSystemAccessControlFactory(new ReadOnlySystemAccessControl.Factory());
addSystemAccessControlFactory(new FileBasedSystemAccessControl.Factory());
addSystemAccessControlFactory(new DenyQueryIntegrityCheckSystemAccessControl.Factory());
}
public void addSystemAccessControlFactory(SystemAccessControlFactory accessControlFactory)
{
requireNonNull(accessControlFactory, "accessControlFactory is null");
if (systemAccessControlFactories.putIfAbsent(accessControlFactory.getName(), accessControlFactory) != null) {
throw new IllegalArgumentException(format("Access control '%s' is already registered", accessControlFactory.getName()));
}
}
public void addCatalogAccessControl(ConnectorId connectorId, ConnectorAccessControl accessControl)
{
requireNonNull(connectorId, "connectorId is null");
requireNonNull(accessControl, "accessControl is null");
checkState(connectorAccessControl.putIfAbsent(connectorId, new CatalogAccessControlEntry(connectorId, accessControl)) == null,
"Access control for connector '%s' is already registered", connectorId);
}
public void removeCatalogAccessControl(ConnectorId connectorId)
{
connectorAccessControl.remove(connectorId);
}
public void loadSystemAccessControl()
throws ExceptionView on GitHub (pinned to 55bb57d202)
Solutions
- Remove duplicate plugin jars so only one provider of that system access control name is installed
- Check the factory's getName() for accidental duplicates
- In tests, create a fresh AccessControlManager or use distinct factory names per registration
- Wrap registration to skip factories already present if idempotent startup is intended
Example fix
// before
accessControlManager.addSystemAccessControlFactory(factory);
// after
if (accessControlManager.getSystemAccessControlFactories().stream()
.noneMatch(f -> f.getName().equals(factory.getName()))) {
accessControlManager.addSystemAccessControlFactory(factory);
} Defensive patterns
Strategy: validation
Validate before calling
boolean alreadyRegistered = manager.getSystemAccessControlFactories().stream()
.anyMatch(f -> f.getName().equals(factory.getName()));
if (alreadyRegistered) { skip-or-log; } Type guard
boolean isRegisterable(SystemAccessControlFactory f, Set<String> registeredNames) {
return f.getName() != null && !registeredNames.contains(f.getName());
} Try / catch
try {
manager.addSystemAccessControlFactory(factory);
} catch (IllegalArgumentException e) {
log.warn("System access control factory already registered: {}", factory.getName());
} Prevention
- Keep only one copy of each access control plugin jar in the plugin directory
- Give custom factories unique, namespaced getName() values
- In tests, build a fresh AccessControlManager per test or register factories once in setup
When it happens
Trigger: Calling addSystemAccessControlFactory with a factory whose name collides with an already-registered factory; most commonly a plugin jar loaded twice, the same plugin installed in multiple plugin directories, or a test calling the method twice for the same factory.
Common situations: Duplicate plugin deployment (same plugin in plugins/ twice or an old and new jar both providing the same access control name); re-registration after a failed bootstrap retried in-process; test setup that adds the factory on every test without resetting the manager.
Related errors
- Session property configuration manager '%s' is already regis
- dictionarySourceIds must be the same
- blocks is empty
- Column does not have same position count (%s) as page (%s)
- QualifiedObjectName should have exactly 3 parts, found %s: %
AI-assisted analysis of prestodb/presto@55bb57d202 (2026-09-04).
Data as JSON: /api/errors/84edcf160b0c573b.
Report an issue: GitHub.