elastic/elasticsearch · error · IllegalArgumentException

Can not use {} with {}

Error message

Can not use {} with {}

What it means

RunTask.validateHelperOption rejects using a CLI/DSL helper option (e.g. `--tls`, debug helpers, APM helpers) when the user has ALSO pre-configured settings under the same prefix via `setting(...)`/`systemProperty(...)`. The helper options exist to shorthand common config; mixing them with explicit settings of the same keys would double-define values ambiguously, so the build refuses rather than guessing precedence.

Source

Thrown at build-tools/src/main/java/org/elasticsearch/gradle/testclusters/RunTask.java:430

            }

            if (thrown != null) {
                logger.debug("exception occurred during close of stdout file readers", thrown);
            }

            if (apmServerEnabled && mockServer != null) {
                mockServer.stop();
            }
        }
    }

    /**
     * Disallow overlap between helper options and explicit configuration
     */
    private void validateHelperOption(String option, String prefix, ElasticsearchNode node) {
        Set<String> preConfigured = findConfiguredSettingsByPrefix(prefix, node);
        if (preConfigured.isEmpty() == false) {
            throw new IllegalArgumentException("Can not use " + option + " with " + String.join(",", preConfigured));
        }
    }

    /**
     * Find any settings configured with a given prefix
     */
    private Set<String> findConfiguredSettingsByPrefix(String prefix, ElasticsearchNode node) {
        Set<String> preConfigured = new HashSet<>();
        node.getSettingKeys().stream().filter(key -> key.startsWith(prefix)).forEach(k -> preConfigured.add(prefix));
        return preConfigured;
    }
}

View on GitHub (pinned to db6a809a66)

Solutions

  1. Remove the explicit setting(s) under the conflicting prefix (the message lists them via `String.join(',', preConfigured)` — note the value is the prefix, so search for keys starting with that prefix).
  2. Alternatively, drop the helper option and keep full manual configuration of that subsystem.
  3. If both are intentional, restructure so the helper owns the entire prefix and the manual settings live under a different namespace.

Example fix

// before
run {
  useCluster(testClusters.c)
  testClusters.c.node.setting('xpack.security.http.ssl.enabled', 'true')
  // plus the TLS helper is enabled elsewhere
}
// after
run {
  useCluster(testClusters.c)
  // let the TLS helper own the ssl.* prefix; remove manual settings
}
Defensive patterns

Strategy: validation

Validate before calling

// Before enabling a helper, scan for manual settings under its prefix
String prefix = helperPrefix; // e.g. 'xpack.security.http.ssl.'
Set<String> conflicts = node.getSettingKeys().stream()
    .filter(k -> k.startsWith(prefix))
    .collect(Collectors.toSet());
if (!conflicts.isEmpty()) {
  throw new IllegalStateException("Helper " + helperName + " conflicts with " + conflicts);
}

Prevention

When it happens

Trigger: Calling a helper like `task.cliDebug`/TLS/APM setup while the same node already has settings whose keys start with the helper's prefix (returned by `findConfiguredSettingsByPrefix`). For example enabling the TLS helper while `node.setting('xpack.security.http.ssl.enabled', ...)` is already set.

Common situations: A developer copies a node config that sets SSL/APM keys manually and then also flips the convenience helper flag; partial migration from manual settings to helper options without removing the originals; profile overlays applied on top of a base that already declared the same keys.

Related errors


AI-assisted analysis of elastic/elasticsearch@db6a809a66 (2026-08-12). Data as JSON: /api/errors/4a2598ebecafbfbf. Report an issue: GitHub.