skip to content

What is an Error in Java, how does it differ from an Exception, and what are some common Error types?

level: middleimportance: should knowfreq 58%

answer

  1. Error = JVM/environment problem, sibling of Exception, unchecked
  2. Don't catch Errors (rare top-level logging exception)
  3. OOM, StackOverflow, NoClassDefFound, AssertionError
  4. NoClassDefFoundError (Error) ≠ ClassNotFoundException (checked)
  5. AssertionError needs -ea to fire

basics

~20 s

An Error signals a serious problem — usually from the JVM or environment — that a normal program isn't expected to recover from, like running out of memory. Exceptions are conditions your code can handle; Errors generally aren't. Common Errors: OutOfMemoryError, StackOverflowError, NoClassDefFoundError, AssertionError.

solid answer

~50 s

Error is a direct subclass of Throwable, sibling to Exception, and is unchecked. It represents abnormal conditions a reasonable application should not try to catch because it usually cannot recover — typically raised by the JVM or runtime rather than business logic. StackOverflowError occurs when the call stack is exhausted, usually from unbounded recursion. OutOfMemoryError occurs when the JVM can't allocate more heap (or other memory regions). NoClassDefFoundError is thrown when a class present at compile time is missing at runtime (distinct from the checked ClassNotFoundException raised by reflective loading). AssertionError is thrown when a Java assert fails. Because Errors are unchecked, the compiler doesn't force handling. Catching Error is discouraged; the rare exceptions are top-level safety nets (e.g. a server loop logging before letting the thread die), and even then catching Throwable broadly is risky.

go deeper

for a junior

Knows Error means a serious JVM-level problem you normally don't catch, and can name OutOfMemoryError and StackOverflowError.

for a middle

Places Error as a sibling of Exception (both under Throwable), explains it's unchecked, and distinguishes NoClassDefFoundError from ClassNotFoundException.

for a senior

Reasons about when (almost never) to catch an Error, the instability after OOM, and the meaning of AssertionError and assertion enablement.

for a principal

Designs resilience strategies for long-running services (top-level safety nets, fail-fast, heap/Metaspace tuning) and educates teams on treating Errors as operational/config signals, not control flow.

## What an Error represents `java.lang.Error` is one of the two direct subclasses of `Throwable` (the other being `Exception`). Its Javadoc says it indicates "serious problems that a reasonable application should not try to catch." These are conditions usually arising from the **JVM or the execution environment itself**, not from ordinary application logic, and for which recovery is typically impossible or unsafe. ``` Throwable ├── Error ← serious, JVM/environment, do not catch └── Exception ← application conditions, often recoverable ``` Like `RuntimeException`, `Error` is **unchecked**: the compiler never forces you to catch or declare it. That makes sense — if the heap is exhausted, requiring every method to declare `throws OutOfMemoryError` would be absurd. ## Error vs Exception — the contract difference | | Error | Exception | |---|---|---| | Origin | JVM / runtime environment | Application logic (and JVM for RuntimeExceptions) | | Recoverable? | Usually no | Usually yes (checked) or it's a bug (RuntimeException) | | Should you catch it? | Almost never | Yes, when you can handle it | | Checked? | No (unchecked) | Checked, except the RuntimeException sub-tree | The key mental model: **Exceptions are about *your program's* problems; Errors are about *the platform's* problems.** ## Common Error types ### StackOverflowError The call stack has a finite size; each method call pushes a frame. Unbounded or excessively deep recursion fills it and throws `StackOverflowError`. ```java int f(int n) { return f(n + 1); } // infinite recursion → StackOverflowError ``` ### OutOfMemoryError The JVM cannot allocate memory and the garbage collector cannot free enough. Variants name the region: "Java heap space", "Metaspace", "GC overhead limit exceeded", "unable to create new native thread". Often a symptom of a memory leak or undersized heap rather than a transient blip. ### NoClassDefFoundError Thrown when the JVM (or a classloader) cannot find the *definition* of a class that **was available when the code was compiled**. Typically a classpath/packaging problem at runtime. Contrast with **`ClassNotFoundException`**, which is a *checked Exception* thrown by *explicit reflective* loading (`Class.forName(...)`, `ClassLoader.loadClass(...)`). One is an Error from the JVM's implicit linking; the other is a checked Exception from your reflective call. (There's also `ExceptionInInitializerError`, thrown when a static initializer blows up.) ### AssertionError Thrown when a Java `assert` statement evaluates to false (assertions must be enabled at runtime with the `-ea` flag). It's an `Error` deliberately: an assertion failure means an invariant the programmer believed *must* hold has been violated, so the program is in an undefined state. ## Should you ever catch an Error? The default answer is **no**. Catching `OutOfMemoryError` or `StackOverflowError` rarely lets you do anything useful, and a broad `catch (Throwable t)` or `catch (Error e)` can mask serious problems and even worsen them. The narrow legitimate cases: - A long-running server's top-level worker loop that wants to **log** the failure and keep the *server* alive while letting the *failing task* die — and even then, you must be careful, because after an `OutOfMemoryError` the JVM may be unstable. - Test frameworks that need to report an `AssertionError` as a failed test rather than crash. Otherwise, treat an `Error` as a signal to fix configuration (heap size), code (recursion, leaks), or packaging (classpath), not as something to handle in flow control. ## Quick disambiguations to remember - `NoClassDefFoundError` (Error, implicit linking) vs `ClassNotFoundException` (checked Exception, explicit reflection). - `StackOverflowError` (Error) vs there is no checked counterpart — deep recursion is always an Error. - `AssertionError` only fires when assertions are *enabled*.

  • What's the difference between NoClassDefFoundError and ClassNotFoundException?
    NoClassDefFoundError is an unchecked Error thrown by the JVM when a class that was present at compile time is missing or fails to link at runtime (a classpath/packaging issue during implicit linking). ClassNotFoundException is a checked Exception thrown when you explicitly try to load a class by name reflectively (Class.forName, ClassLoader.loadClass) and it isn't found. Same root cause shape, but different mechanism and different place in the hierarchy.
  • Is it ever acceptable to catch an Error?
    Rarely. A top-level server loop may catch Throwable to log the failure and avoid killing the whole process while letting the offending task die, and test frameworks catch AssertionError to report failures. Beyond those, catching Errors like OutOfMemoryError is discouraged because recovery is usually impossible and the JVM may already be unstable.

saying these in an interview costs you the question

  • Saying Error is checked — it's unchecked
  • Confusing NoClassDefFoundError (Error, implicit linking) with ClassNotFoundException (checked, reflection)
  • Routinely catching OutOfMemoryError expecting to recover
  • Calling Error a subclass of Exception — it's a sibling, both directly under Throwable
  • Assuming assert statements always run — they need to be explicitly enabled

context