prestodb/presto · error · PrestoException
GENERIC_INTERNAL_ERROR
GENERIC_INTERNAL_ERROR
Error message
Operator %s has non-zero system memory (%d bytes) after destroy()
What it means
OperatorContext.destroy closes the operator's memory context then asserts the operator released all system memory. A non-zero remaining system memory reservation after destroy() is an internal invariant violation (a leak in the operator implementation), thrown as GENERIC_INTERNAL_ERROR.
Source
Thrown at presto-main-base/src/main/java/com/facebook/presto/operator/OperatorContext.java:406
public void destroy()
{
// reset memory revocation listener so that OperatorContext doesn't hold any references to Driver instance
synchronized (this) {
memoryRevocationRequestListener = null;
}
// memoize the result of and then clear any reference to the original suppliers (which might otherwise retain operators or other large objects)
Supplier<? extends OperatorInfo> infoSupplier = this.infoSupplier.get();
if (infoSupplier != null) {
OperatorInfo info = infoSupplier.get();
this.infoSupplier.set(info == null ? null : Suppliers.ofInstance(info));
}
operatorMemoryContext.close();
if (operatorMemoryContext.getSystemMemory() != 0) {
throw new PrestoException(GENERIC_INTERNAL_ERROR, format("Operator %s has non-zero system memory (%d bytes) after destroy()", this, operatorMemoryContext.getSystemMemory()));
}
if (operatorMemoryContext.getUserMemory() != 0) {
throw new PrestoException(GENERIC_INTERNAL_ERROR, format("Operator %s has non-zero user memory (%d bytes) after destroy()", this, operatorMemoryContext.getUserMemory()));
}
if (operatorMemoryContext.getRevocableMemory() != 0) {
throw new PrestoException(GENERIC_INTERNAL_ERROR, format("Operator %s has non-zero revocable memory (%d bytes) after destroy()", this, operatorMemoryContext.getRevocableMemory()));
}
}
public SpillContext getSpillContext()
{
return spillContext;
}
public void moreMemoryAvailable()
{View on GitHub (pinned to 55bb57d202)
Solutions
- Fix the operator to release/reserve-free all system memory before or during close/destroy
- Update Presto — this class of leak is often fixed in later releases
- Capture the operator name from the message and report with the plan fragment to isolate the leaking operator
Example fix
// before close(); // after (operator must release before context close) localSystemMemoryContext.close(); // frees tracked allocations buffer = null;
Defensive patterns
Strategy: try-catch
Validate before calling
// operator authors: assert released before close
if (systemMemoryContext.getBytes() != 0) { systemMemoryContext.setBytes(0); } Try / catch
// engine-side; users should catch and escalate as a bug report
try { executeQuery(sql); } catch (PrestoException e) {
if (e.getMessage() != null && e.getMessage().contains("non-zero system memory")) {
log.error("Operator memory leak after destroy", e); // file bug with operator name
}
} Prevention
- Operator authors: always close LocalMemoryContexts in close()/finally blocks
- Keep Presto upgraded — leaks are routinely patched
- Never swallow exceptions in operator cleanup paths
When it happens
Trigger: destroy() is called during operator teardown while operatorMemoryContext.getSystemMemory() != 0, i.e. an operator allocated system memory (e.g. buffers, native allocations) and never freed/reserved-released it.
Common situations: Custom operator/connector bugs leaking memory contexts; failed operators that skip cleanup paths; pagination/buffer not set to null before close.
Related errors
- Unsupported java type %s
- CLICKHOUSE_QUERY_GENERATOR_FAILURE
- Unsupported flip non-comparison operator:
- Unsupported negate non-comparison operator:
- KdbTree type cannot be serialized
AI-assisted analysis of prestodb/presto@55bb57d202 (2026-09-04).
Data as JSON: /api/errors/f584f731173b3bc2.
Report an issue: GitHub.