{"record":{"id":"af372c0935dfaa2a","repo":"apache/druid","slug":"not-enough-direct-memory-please-adjust-xx-maxdi","errorCode":null,"errorMessage":"Not enough direct memory.  Please adjust -XX:MaxDirectMemorySize, druid.processing.buffer.sizeBytes, or druid.processing.numMergeBuffers: maxDirectMemory[%,d], memoryNeeded[%,d] = druid.processing.buffer.sizeBytes[%,d] * (druid.processing.numMergeBuffers[%,d] + 1)","messagePattern":"Not enough direct memory\\.  Please adjust -XX:MaxDirectMemorySize, druid\\.processing\\.buffer\\.sizeBytes, or druid\\.processing\\.numMergeBuffers: maxDirectMemory\\[%,d\\], memoryNeeded\\[%,d\\] = druid\\.processing\\.buffer\\.sizeBytes\\[%,d\\] \\* \\(druid\\.processing\\.numMergeBuffers\\[%,d\\] \\+ 1\\)","errorType":"exception","errorClass":"ProvisionException","httpStatus":null,"severity":"critical","filePath":"server/src/main/java/org/apache/druid/guice/BrokerProcessingModule.java","lineNumber":157,"sourceCode":"  }\n\n  @Provides\n  @Merging\n  public ForkJoinPool getMergeProcessingPool(LifecycleForkJoinPoolProvider poolProvider)\n  {\n    return poolProvider.getPool();\n  }\n\n  private void verifyDirectMemory(DruidProcessingConfig config, RuntimeInfo runtimeInfo)\n  {\n    final long memoryNeeded = (long) config.intermediateComputeSizeBytes() *\n                              (config.getNumMergeBuffers() + 1);\n\n    try {\n      final long maxDirectMemory = runtimeInfo.getDirectMemorySizeBytes();\n\n      if (maxDirectMemory < memoryNeeded) {\n        throw new ProvisionException(\n            StringUtils.format(\n                \"Not enough direct memory.  Please adjust -XX:MaxDirectMemorySize, druid.processing.buffer.sizeBytes, or druid.processing.numMergeBuffers: \"\n                + \"maxDirectMemory[%,d], memoryNeeded[%,d] = druid.processing.buffer.sizeBytes[%,d] * (druid.processing.numMergeBuffers[%,d] + 1)\",\n                maxDirectMemory,\n                memoryNeeded,\n                config.intermediateComputeSizeBytes(),\n                config.getNumMergeBuffers()\n            )\n        );\n      }\n    }\n    catch (UnsupportedOperationException e) {\n      log.debug(\"Checking for direct memory size is not support on this platform: %s\", e);\n      log.info(\n          \"Your memory settings require at least %,d bytes of direct memory. \"\n          + \"Your machine must have at least this much memory available, and your JVM \"\n          + \"-XX:MaxDirectMemorySize parameter must be at least this high. \"\n          + \"If it is, you may safely ignore this message. \"","sourceCodeStart":139,"sourceCodeEnd":175,"githubUrl":"https://github.com/apache/druid/blob/9b90983fd291f26935af934383ce360473179e4d/server/src/main/java/org/apache/druid/guice/BrokerProcessingModule.java#L139-L175","documentation":"BrokerProcessingModule.verifyDirectMemory checks at Guice provision time that the JVM's max direct memory can hold the intermediate-results pool plus all merge buffers: buffer.sizeBytes * (numMergeBuffers + 1). If MaxDirectMemorySize is smaller, provisioning fails with this ProvisionException so the broker refuses to start misconfigured.","triggerScenarios":"Starting a Broker where druid.processing.buffer.sizeBytes * (druid.processing.numMergeBuffers + 1) exceeds -XX:MaxDirectMemorySize; getIntermediateResultsPool or getMergeBufferPool is provisioned.","commonSituations":"Docker/K8s containers with low default direct memory; raising numMergeBuffers or buffer size without raising -XX:MaxDirectMemorySize; forgetting that JVM default max direct memory may equal heap size.","solutions":["Increase -XX:MaxDirectMemorySize to at least buffer.sizeBytes * (numMergeBuffers + 1)","Lower druid.processing.buffer.sizeBytes","Lower druid.processing.numMergeBuffers","Verify with the printed maxDirectMemory/memoryNeeded numbers in the message"],"exampleFix":"// before\nJAVA_OPTS=\"-Xmx4g\" # direct memory defaults too low\n// after\nJAVA_OPTS=\"-Xmx4g -XX:MaxDirectMemorySize=6g\"","handlingStrategy":"validation","validationCode":"long bufferBytes = config.intermediateComputeSizeBytes();\nlong needed = bufferBytes * (config.getNumMergeBuffers() + 1L);\nif (runtimeInfo.getDirectMemorySizeBytes() < needed) {\n  throw new IllegalStateException(\"raise -XX:MaxDirectMemorySize to >= \" + needed);\n}","typeGuard":null,"tryCatchPattern":"try {\n  injector = GuiceInjectors.makeStartupInjector(...);\n} catch (ProvisionException e) {\n  if (e.getMessage().contains(\"Not enough direct memory\")) {\n    log.error(\"Reconfigure -XX:MaxDirectMemorySize or druid.processing buffers\");\n    System.exit(1);\n  }\n  throw e;\n}","preventionTips":["Set -XX:MaxDirectMemorySize explicitly in every broker start script/container","Recompute direct memory whenever numMergeBuffers or buffer.sizeBytes changes","In containers, account for JVM direct memory beyond heap limits","Smoke-test broker startup after processing config changes"],"tags":["memory","configuration","startup"],"backgroundTag":"invalid-config-value","analyzedSha":"9b90983fd291f26935af934383ce360473179e4d","analyzedAt":"2026-09-07T13:32:30.957Z","contentChangedAt":"2026-09-07T13:32:30.957Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}