What it means
NoClassDefFoundError is thrown when the JVM successfully resolved a class at compile time but cannot produce a usable definition of it now. That is a different statement from ClassNotFoundException, which means nobody could find the class at all, and the difference determines where to look.
The case that makes this error genuinely confusing on Lambda is static initialisation. A class's static block and static field initialisers run exactly once, the first time the class is touched. If any of that throws, the JVM marks the class erroneous — permanently, for the lifetime of that JVM. The first failure surfaces as ExceptionInInitializerError and carries the real exception with a real stack trace. Every subsequent use of that class, for as long as the execution environment lives, throws NoClassDefFoundError: Could not initialize class … with no indication of the original cause.
On Lambda this interacts badly with execution-environment reuse. One container serves many invocations. The class is poisoned on invocation 1, and invocations 2 through 200 on that same container all fail with the uninformative echo — each under its own request ID, each looking like an independent failure. Meanwhile a different container that never took that code path keeps succeeding, so the function appears to fail intermittently at a stable rate. It is not intermittent: it is deterministic per container.
That is also why this is one of the errors most worth reading against a whole log stream rather than a single invocation. The invocation you are looking at contains the echo. The invocation that contains the answer happened earlier, under a request ID you have no reason to search for, and the only thing connecting them is that they ran in the same execution environment.
CloudWatch’s Errors metric: The error escaped your handler, so Lambda reports the invocation as failed and CloudWatch’s Errors metric counts it. The class cannot be used, so the invocation fails and CloudWatch counts it. LogStitch extracts the type NoClassDefFoundError but reports the failure as unclassified rather than uncaught, since a log line alone cannot show whether the calling code caught it.
What it looks like in CloudWatch
This is the shape the failure arrives in: the lines of one invocation scattered among everything else the log group received at the same moment.
CloudWatch Logs Before
6 raw lines, in the order CloudWatch delivered them.
LogStitch After
The same lines, grouped into the invocation they belong to.
Errore91c4a77-2b63-4d05-8f19-6c2a7e3b0d41
- 09:20:11.402PLAT
START RequestId: e91c4a77-2b63-4d05-8f19-6c2a7e3b0d41 Version: $LATEST
- 09:20:11.688
java.lang.NoClassDefFoundError: Could not initialize class com.example.orders.PricingConfig at com.example.orders.OrderHandler.price(OrderHandler.java:74) at com.example.orders.OrderHandler.handleRequest(OrderHandler.java:38)
3 lines - 09:20:11.902PLAT
END RequestId: e91c4a77-2b63-4d05-8f19-6c2a7e3b0d41
- 09:20:11.902PLAT
REPORT RequestId: e91c4a77-2b63-4d05-8f19-6c2a7e3b0d41 Duration: 500.11 ms Billed Duration: 501 ms Memory Size: 1024 MB Max Memory Used: 251 MB Status: error
The panel on the right is generated by running the excerpt on the left through the same parser that powers the free web stitcher — it is what the tool actually produces for this input, not an illustration of it.
How to confirm it from the logs
The wording separates the two cases, and it is worth reading carefully. A bare NoClassDefFoundError: com/example/Thing (note the slashes — this is an internal class name, not a package name) usually means the class is genuinely absent. Could not initialize class com.example.Thing means the opposite: it was found, and its static setup failed.
For the second case, look earlier in the same invocation, or in an earlier invocation on the same container. The real exception — the one the static initialiser threw — was logged the first time the class was touched. Every subsequent attempt produces this far less informative error instead. If you only look at the failing invocation you will never see the cause, because it was reported minutes earlier under a different request ID.
Causes, most likely first
A static initialiser threw an exception the first time the class was loaded
Search the log stream for an ExceptionInInitializerError or any exception whose stack trace includes <clinit>, before the first NoClassDefFoundError. Reading an environment variable that is not set, or building a client from a missing configuration value, at static scope is the usual culprit.
The class is missing from the deployment artifact
List the artifact's contents and look for the class file. If it is absent, this behaves like ClassNotFoundException and the fix is the same — the build is not packaging dependencies.
A transitive dependency is absent while its dependent is present
Check whether the missing class belongs to a library you never depend on directly. A jar that made it into the bundle can reference classes from another that did not, and the failure only appears when the code path needing it runs.
Two versions of the library are on the classpath
Print the dependency tree and look for the class's library more than once. A class removed or moved between versions is compiled against one and resolved against the other, which produces this error without anything obviously missing.
Fixes
Find the original initialiser failure before changing anything
When the message says "Could not initialize class", this error is an echo — the useful exception was thrown and logged the first time the class was touched, possibly on an earlier invocation on the same container. Find that first, because fixing anything else is guesswork.
bash# Look for the original failure, not the echo.
aws logs filter-log-events \
--log-group-name /aws/lambda/order-function \
--filter-pattern 'ExceptionInInitializerError' \
--start-time $(( ($(date +%s) - 3600) * 1000 ))
Move risky setup out of static initialisers
Static initialisation runs once and cannot be retried. If it can fail — a missing environment variable, an unreachable endpoint, a parse of external configuration — move it into the handler or make it lazy, so a failure is a normal exception on one invocation rather than a permanently broken class.
java// Risky: throws at class load, poisons the class for the whole container.
// private static final String TABLE = System.getenv("TABLE").trim();
// Safer: fails per invocation, with a message that says what is wrong.
private static String table() {
String value = System.getenv("TABLE");
if (value == null) {
throw new IllegalStateException("TABLE environment variable is not set");
}
return value;
}
Package the dependencies properly
Where the class really is absent, the cause is the same as any other missing-class failure: the artifact contains your compiled classes and nothing else. Build an uber-jar, or a zip with the dependencies under lib/.
bashmvn clean package shade:shade
unzip -l target/function.jar | grep -c '\.class$'
Also seen as
The same underlying failure, worded differently by a different runtime, SDK version, or logging layer. All of these land here — there is no separate page for each phrasing.
Related errors
Errors that show up alongside this one, or that people mistake for it.
References
- AWS Lambda Developer Guide — Define Lambda function handler in Java
- Java SE API — NoClassDefFoundError
LogStitch finds this automatically, across every invocation in your account.
Paste a log excerpt into the free web stitcher and see it grouped, classified, and measured in your browser — nothing is uploaded. Or run the Mac app against your own AWS profiles and get the same view over every function you own.