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
- Increase -XX:MaxDirectMemorySize to at least buffer.sizeBytes * (numMergeBuffers + numThreads + 1)
- Reduce druid.processing.numThreads or druid.processing.numMergeBuffers
- Reduce druid.processing.buffer.sizeBytes
- 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
- Compute required direct memory in deployment templates: sizeBytes*(numMergeBuffers+numThreads+1)
- Keep -XX:MaxDirectMemorySize explicit on historicals and peons
- Re-validate after any change to numThreads, numMergeBuffers, or buffer.sizeBytes
- Watch direct memory usage metrics in production
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
- druid.processing.buffer.sizeBytes must be less than 2GiB
- Not enough direct memory. Please adjust…
- At least one of the druid.enablePlaintextPort or…
- Config[ ] has been removed. Please use config[ ] instead.
- Dot at the end of property
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)