apache/druid · critical · ProvisionException

Not enough direct memory. Please adjust…

Error message

Not enough direct memory.  Please adjust -XX:MaxDirectMemorySize, druid.processing.buffer.sizeBytes, druid.processing.numThreads, or druid.processing.numMergeBuffers: maxDirectMemory[%,d], memoryNeeded[%,d] = druid.processing.buffer.sizeBytes[%,d] * (druid.processing.numMergeBuffers[%,d] + druid.processing.numThreads[%,d] + 1)

What it means

DruidProcessingModule.verifyDirectMemory runs at Guice provision time on processing nodes (historicals/peons) and requires max direct memory >= buffer.sizeBytes * (numMergeBuffers + numThreads + 1). If MaxDirectMemorySize is too small, startup fails with this ProvisionException listing exact numbers.

Solutions

  1. Increase -XX:MaxDirectMemorySize to at least buffer.sizeBytes * (numMergeBuffers + numThreads + 1)
  2. Reduce druid.processing.numThreads or druid.processing.numMergeBuffers
  3. Reduce druid.processing.buffer.sizeBytes
  4. Use the numbers in the error message to compute the exact required size

Example fix

// before
-XX:MaxDirectMemorySize=2g  # with sizeBytes=1g, numThreads=5, mergeBuffers=2 -> needs 8g
// after
-XX:MaxDirectMemorySize=8g
Defensive patterns

Strategy: validation

Validate before calling

long bufferBytes = config.intermediateComputeSizeBytes();
long needed = bufferBytes * (config.getNumMergeBuffers() + config.getNumThreads() + 1L);
if (runtimeInfo.getDirectMemorySizeBytes() < needed) {
  throw new IllegalStateException("raise -XX:MaxDirectMemorySize to >= " + needed);
}

Try / catch

try {
  injector = makeInjector();
} catch (ProvisionException e) {
  if (e.getMessage().contains("Not enough direct memory")) {
    log.error("Set -XX:MaxDirectMemorySize >= sizeBytes*(numMergeBuffers+numThreads+1)");
    throw e;
  }
  throw e;
}

Prevention

When it happens

Trigger: Starting a historical/task JVM where druid.processing.buffer.sizeBytes * (druid.processing.numMergeBuffers + druid.processing.numThreads + 1) exceeds -XX:MaxDirectMemorySize; triggered by createIntermediateResultsPool or createMergeBufferPool provisioning.

Common situations: Containers with small direct memory defaults; increasing numThreads/numMergeBuffers or buffer size without resizing direct memory; Peon workers inheriting too-small -XX:MaxDirectMemorySize.

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/76cefbdb05e240dc. Report an issue: GitHub.

Appendix: source

Thrown at server/src/main/java/org/apache/druid/guice/DruidProcessingModule.java:201

  )
  {
    verifyDirectMemory(config, runtimeInfo);
    return new DefaultBlockingPool<>(
        new OffheapBufferGenerator("result merging", config.intermediateComputeSizeBytes()),
        config.getNumMergeBuffers(),
        config.isParallelMemoryPoolInit()
    );
  }

  private static void verifyDirectMemory(final DruidProcessingConfig config, final RuntimeInfo runtimeInfo)
  {
    try {
      final long maxDirectMemory = runtimeInfo.getDirectMemorySizeBytes();
      final long memoryNeeded = (long) config.intermediateComputeSizeBytes() *
                                (config.getNumMergeBuffers() + config.getNumThreads() + 1);

      if (maxDirectMemory < memoryNeeded) {
        throw new ProvisionException(
            StringUtils.format(
                "Not enough direct memory.  Please adjust -XX:MaxDirectMemorySize, druid.processing.buffer.sizeBytes, druid.processing.numThreads, or druid.processing.numMergeBuffers: "
                + "maxDirectMemory[%,d], memoryNeeded[%,d] = druid.processing.buffer.sizeBytes[%,d] * (druid.processing.numMergeBuffers[%,d] + druid.processing.numThreads[%,d] + 1)",
                maxDirectMemory,
                memoryNeeded,
                config.intermediateComputeSizeBytes(),
                config.getNumMergeBuffers(),
                config.getNumThreads()
            )
        );
      }
    }
    catch (UnsupportedOperationException e) {
      log.debug("Checking for direct memory size is not support on this platform: %s", e);
      log.info(
          "Unable to determine max direct memory size. If druid.processing.buffer.sizeBytes is explicitly configured, "
          + "then make sure to set -XX:MaxDirectMemorySize to at least \"druid.processing.buffer.sizeBytes * "
          + "(druid.processing.numMergeBuffers[%,d] + druid.processing.numThreads[%,d] + 1)\", "

View on GitHub (pinned to 9b90983fd2)