Skip to content
Latchkey

Clojure AOT compilation OutOfMemoryError in CI

AOT compilation (during lein uberjar or a tools.build compile-clj) loads and compiles every namespace, which is memory-heavy. On a constrained runner the compiling JVM can exceed its heap and throw OutOfMemoryError.

What this error means

An uberjar or AOT build fails with "java.lang.OutOfMemoryError: Java heap space" (or GC overhead limit exceeded) partway through compiling namespaces.

JVM
Compiling myapp.core
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
    at clojure.lang.Compiler ...

Common causes

The compiling JVM heap is too small

AOT holds many loaded classes in memory; a default or low -Xmx on the runner is exhausted before compilation finishes.

A large namespace graph compiled at once

A big app AOT-compiling all namespaces (rather than just the entry) needs more heap than the runner allots.

How to fix it

Raise the JVM heap for the build

Give the compiling JVM more heap through the tool-specific options variable.

Terminal
# Leiningen
export JVM_OPTS="-Xmx4g"
lein uberjar
# tools.build
clojure -J-Xmx4g -T:build uber

Limit AOT to the entry namespace

Skip AOT on the rest of the tree so only what needs compiling is compiled.

project.clj
(defproject myapp "0.1.0"
  :main ^:skip-aot myapp.core
  :aot [myapp.core])

How to prevent it

  • Set an explicit -Xmx for AOT/uberjar builds on constrained runners.
  • AOT only the namespaces that must be compiled.
  • Use a runner with enough memory for the compile step.

Frequently asked questions

What causes "AOT "OutOfMemoryError""?
AOT holds many loaded classes in memory; a default or low -Xmx on the runner is exhausted before compilation finishes.
How do I fix AOT "OutOfMemoryError"?
Give the compiling JVM more heap through the tool-specific options variable.

Related guides

References

Latchkey auto-heals failures like this one - detected, fixed, and retried without you. Start free → 30-day trial · No credit card