apache/druid · error · RuntimeException

Invalid value provided for `druid.cache.clientMode`. Value…

Error message

Invalid value provided for `druid.cache.clientMode`. Value must be 'static' or 'dynamic'.

What it means

MemcachedCache validates the `druid.cache.clientMode` config when building the spyMemcached connection factory. Only 'static' (fixed host list) and 'dynamic' (host discovery) are supported by the underlying spymemcached ClientMode enum; anything else is rejected at cache initialization.

Solutions

  1. Set druid.cache.clientMode=static or druid.cache.clientMode=dynamic (exact lowercase strings)
  2. Remove the property to rely on the config default
  3. Check spelling/case against the accepted values in MemcachedCacheConfig

Example fix

// before
druid.cache.clientMode=Static
// after
druid.cache.clientMode=static
Defensive patterns

Strategy: validation

Validate before calling

final String mode = config.getClientMode();
if (!"static".equals(mode) && !"dynamic".equals(mode)) {
  throw new IllegalArgumentException("druid.cache.clientMode must be 'static' or 'dynamic', got: " + mode);
}

Type guard

static boolean isValidClientMode(final String mode) {
  return "static".equals(mode) || "dynamic".equals(mode);
}

Prevention

When it happens

Trigger: Setting druid.cache.type=memcached with druid.cache.clientMode set to any value other than exactly 'static' or 'dynamic' (typo, capitalized like 'Static', or leftover from another config).

Common situations: Copy-pasting cache config from another product, using camelCase or capitalized values, editing runtime.properties by hand and mistyping the enum.

Understand the failure class

Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.

Related errors


AI-assisted analysis of apache/druid@9b90983fd2 (2026-09-07). Data as JSON: /api/errors/f3e58681a86f3677. Report an issue: GitHub.

Appendix: source

Thrown at server/src/main/java/org/apache/druid/client/cache/MemcachedCache.java:427

            .setOpQueueFactory(opQueueFactory)
            .setMetricCollector(metricCollector)
            .setEnableMetrics(MetricType.DEBUG); // Not as scary as it sounds
    if (config.enableTls()) {
      // Build SSLContext
      TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
      tmf.init((KeyStore) null);
      SSLContext sslContext = SSLContext.getInstance("TLSv1.2");
      sslContext.init(null, tmf.getTrustManagers(), null);
      // Create the client in TLS mode
      connectionFactoryBuilder.setSSLContext(sslContext);
    }
    if ("dynamic".equals(config.getClientMode())) {
      connectionFactoryBuilder.setClientMode(ClientMode.Dynamic);
      connectionFactoryBuilder.setHostnameForTlsVerification(config.getHosts().split(",")[0]);
    } else if ("static".equals(config.getClientMode())) {
      connectionFactoryBuilder.setClientMode(ClientMode.Static);
    } else {
      throw new RuntimeException("Invalid value provided for `druid.cache.clientMode`. Value must be 'static' or 'dynamic'.");
    }
    connectionFactoryBuilder.setSkipTlsHostnameVerification(config.skipTlsHostnameVerification());
    return connectionFactoryBuilder.build();
  }

  private final int timeout;
  private final int expiration;
  private final String memcachedPrefix;

  private final Supplier<ResourceHolder<MemcachedClientIF>> client;

  private final AtomicLong hitCount = new AtomicLong(0);
  private final AtomicLong missCount = new AtomicLong(0);
  private final AtomicLong timeoutCount = new AtomicLong(0);
  private final AtomicLong errorCount = new AtomicLong(0);
  private final AbstractMonitor monitor;

View on GitHub (pinned to 9b90983fd2)