prestodb/presto · error · IllegalArgumentException

Node ttl fetcher factory '%s' is already registered

Error message

Node ttl fetcher factory '%s' is already registered

What it means

ConfidenceBasedNodeTtlFetcherManager.addNodeTtlFetcherFactory throws IllegalArgumentException when a NodeTtlFetcherFactory with a name already present in ttlFetcherFactories is registered (putIfAbsent returns non-null). Each node TTL fetcher factory must have a unique name within the manager.

Source

Thrown at presto-main-base/src/main/java/com/facebook/presto/ttl/nodettlfetchermanagers/ConfidenceBasedNodeTtlFetcherManager.java:171

    public Optional<NodeTtl> getTtlInfo(InternalNode node)
    {
        return nodeTtlMap.containsKey(node) ? Optional.of(nodeTtlMap.get(node)) : Optional.empty();
    }

    @Override
    public Map<InternalNode, NodeTtl> getAllTtls()
    {
        return ImmutableMap.copyOf(nodeTtlMap);
    }

    @Override
    public void addNodeTtlFetcherFactory(NodeTtlFetcherFactory nodeTtlFetcherFactory)
    {
        requireNonNull(nodeTtlFetcherFactory, "nodeTtlFetcherFactory is null");

        if (ttlFetcherFactories.putIfAbsent(nodeTtlFetcherFactory.getName(), nodeTtlFetcherFactory) != null) {
            throw new IllegalArgumentException(format("Node ttl fetcher factory '%s' is already registered", nodeTtlFetcherFactory.getName()));
        }
    }

    @Override
    public void loadNodeTtlFetcher()
            throws Exception
    {
        String factoryName = "infinite";
        Map<String, String> properties = ImmutableMap.of();

        if (Files.exists(TTL_FETCHER_CONFIG)) {
            properties = new HashMap<>(loadProperties(TTL_FETCHER_CONFIG.toFile()));
            factoryName = properties.remove(TTL_FETCHER_PROPERTY_NAME);

            checkArgument(!isNullOrEmpty(factoryName),
                    "Node ttl fetcher configuration %s does not contain %s", TTL_FETCHER_CONFIG.toAbsolutePath(), TTL_FETCHER_PROPERTY_NAME);
        }

View on GitHub (pinned to 55bb57d202)

Solutions

  1. Deduplicate plugin jars / ensure only one plugin registers the fetcher factory.
  2. Give one of the colliding factories a unique getName().
  3. Instantiate a new ConfidenceBasedNodeTtlFetcherManager instead of re-registering into an existing one.
  4. Wrap registration in a contains-check or try-catch to make setup idempotent in tests.

Example fix

// before
nodeTtlFetcherManager.addNodeTtlFetcherFactory(new JmxNodeTtlFetcherFactory("jmx"));
nodeTtlFetcherManager.addNodeTtlFetcherFactory(new JmxNodeTtlFetcherFactory("jmx")); // throws

// after
NodeTtlFetcherFactory factory = new JmxNodeTtlFetcherFactory("jmx");
try {
    nodeTtlFetcherManager.addNodeTtlFetcherFactory(factory);
} catch (IllegalArgumentException e) {
    // already registered — skip
}
Defensive patterns

Strategy: try-catch

Validate before calling

// Ensure the fetcher factory name is not already present before registering
boolean exists = nodeTtlFetcherManager.getNodeTtlFetcherFactories().stream()
    .anyMatch(f -> f.getName().equals(factory.getName()));
if (!exists) {
    nodeTtlFetcherManager.addNodeTtlFetcherFactory(factory);
}

Type guard

boolean isFetcherNameFree(ConfidenceBasedNodeTtlFetcherManager m, String name) {
    return m.getNodeTtlFetcherFactories().stream().noneMatch(f -> f.getName().equals(name));
}

Try / catch

try {
    nodeTtlFetcherManager.addNodeTtlFetcherFactory(factory);
} catch (IllegalArgumentException e) {
    LOG.warn("Node ttl fetcher factory '%s' already registered; skipping", factory.getName());
}

Prevention

When it happens

Trigger: Calling addNodeTtlFetcherFactory with a factory whose getName() is already registered — duplicate plugin load, two plugins shipping the same fetcher factory name, or repeated setup() invocations on the same manager instance (noted by its callers testTtlAwareScheduling and setup).

Common situations: Duplicate node-ttl plugin jars deployed to workers; two TTL plugins colliding on factory name; tests calling setup twice; hot plugin reload re-registering the same factory.

Related errors


AI-assisted analysis of prestodb/presto@55bb57d202 (2026-09-04). Data as JSON: /api/errors/7c199a09e216b367. Report an issue: GitHub.