Hero Background

Next-Gen App & Browser Testing Cloud

Trusted by 2 Mn+ QAs & Devs to accelerate their release cycles

Next-Gen App & Browser Testing Cloud

What Is the Difference Between an Error and an Exception?

In Java, an Error is a serious, usually unrecoverable problem that the application should not try to handle — such as OutOfMemoryError or StackOverflowError — while an Exception is a condition the application can catch and recover from, such as IOException or NullPointerException. Both Error and Exception extend the common superclass Throwable, but only Exceptions are meant to be caught and handled in normal program flow.

Below, we break down the Throwable hierarchy, compare Errors and Exceptions side by side, explain checked versus unchecked exceptions, show how to handle exceptions with try/catch/finally, and clear up the related testing terms — error, defect, bug, and failure.

What Is an Error

An Error represents a serious problem that a reasonable application should not try to catch. In Java these are subclasses of java.lang.Error, and they almost always originate from the environment the program runs in — the JVM, the operating system, or the hardware — rather than from a logical mistake in a single line of business code. Errors typically surface at runtime, indicate the system is in an abnormal state, and are generally unrecoverable.

Classic examples include:

  • OutOfMemoryError — the JVM cannot allocate more objects because the heap is exhausted.
  • StackOverflowError — usually caused by infinite or excessively deep recursion that fills the call stack.
  • NoClassDefFoundError — a class that was present at compile time is missing at runtime.
  • VirtualMachineError — the JVM itself is broken or has run out of the resources it needs to keep operating.

Because these conditions reflect the health of the runtime, catching them rarely helps. The correct response is usually to let the application terminate, then fix the root cause — increase the heap size, remove the runaway recursion, or correct the deployment so the missing class is on the classpath.

What Is an Exception

An Exception is an event that disrupts the normal flow of a program but which the application can anticipate, catch, and recover from. Exceptions are subclasses of java.lang.Exception and usually originate in the application code or the data it processes — a missing file, a bad network response, a null reference, or an invalid array index. Unlike Errors, exceptions are a normal, expected part of robust programming, and handling them gracefully is what keeps an application running instead of crashing.

Common examples include:

  • IOException — a file or network read/write failed; a checked exception you must handle.
  • NullPointerException — your code accessed a member on a null reference; an unchecked exception.
  • ArrayIndexOutOfBoundsException — an index outside the array bounds was used.
  • NumberFormatException — a string that is not a valid number was parsed into one.

The key distinction is intent: exceptions are designed to be caught. When an exception occurs, your code can log it, retry the operation, fall back to a default, or surface a friendly message to the user, and then continue running. If you are new to the concept, our primer on what exceptions mean covers the fundamentals in more detail.

The Throwable Hierarchy

Everything that can be thrown or caught in Java descends from a single root class, java.lang.Throwable. Directly beneath it sit two branches — Error and Exception — which makes them siblings, not parent and child. Under Exception, the RuntimeException branch holds the unchecked exceptions, while every other Exception subclass is checked.

java.lang.Throwable
 ├── java.lang.Error                 // serious, do NOT catch
 │    ├── OutOfMemoryError
 │    ├── StackOverflowError
 │    └── NoClassDefFoundError
 └── java.lang.Exception             // catch and recover
      ├── IOException                // checked
      ├── SQLException               // checked
      └── java.lang.RuntimeException // unchecked
           ├── NullPointerException
           ├── ArrayIndexOutOfBoundsException
           └── NumberFormatException

Because both branches extend Throwable, you could write catch (Throwable t) to trap an Error, but that is almost always the wrong choice — it hides serious JVM failures behind ordinary error handling. The hierarchy exists precisely so you can catch Exception (and its subclasses) without accidentally swallowing an Error.

Error vs Exception (Comparison)

The following summarizes the practical differences testers and developers care about most:

  • Cause: Error - the environment, JVM, OS, or hardware running low on resources; Exception - the application code or the data it processes.
  • Recoverable?: Error - No, generally unrecoverable; the program should terminate; Exception - Yes, can be caught, handled, and recovered from.
  • Should you catch it?: Error - No, catching it usually hides a fatal condition; Exception - Yes, catching and handling is normal, expected practice.
  • Checked or unchecked?: Error - Always unchecked; Exception - Can be checked or unchecked (RuntimeException).
  • When detected?: Error - Only at runtime; Exception - Checked exceptions at compile time; unchecked at runtime.
  • Effect on program: Error - Program usually terminates abruptly; Exception - If caught, the program keeps running; if not, it terminates.
  • Package: Error - Defined under java.lang.Error; Exception - Defined under java.lang.Exception.
  • Examples: Error - OutOfMemoryError, StackOverflowError, NoClassDefFoundError; Exception - IOException, NullPointerException, SQLException.

Checked vs Unchecked Exceptions

Within the Exception branch, Java draws a second important line. A checked exception is verified by the compiler: if a method can throw one, you must either catch it or declare it with throws, or the code will not compile. IOException, SQLException, and ClassNotFoundException are checked. They model recoverable conditions outside your control, like a file that may not exist.

An unchecked exception extends RuntimeException and is not enforced by the compiler. NullPointerException, ArrayIndexOutOfBoundsException, and NumberFormatException are unchecked. They usually signal a programming bug that you should fix rather than catch. The contrast is shown below:

// CHECKED — compiler forces you to handle or declare it
public void readFile(String path) throws IOException {
    FileReader reader = new FileReader(path); // may throw IOException
    reader.read();
    reader.close();
}

// UNCHECKED — compiles fine, fails only at runtime
public int parse(String value) {
    return Integer.parseInt(value); // throws NumberFormatException if not a number
}

A useful mnemonic: checked = "expected, handle it" and unchecked = "your bug, fix it." Errors, for completeness, are also unchecked — the compiler never forces you to handle them.

Handling Exceptions in Java

Java handles exceptions with the try, catch, and finally blocks. Code that might throw goes in try; each catch handles a specific exception type (most specific first); and finally always runs, whether or not an exception occurred, making it ideal for releasing resources. For a deeper treatment of the mechanisms, types, and patterns involved, see our full guide to exception handling.

public class FileProcessor {
    public static void main(String[] args) {
        try {
            int[] data = readNumbers("data.txt");
            System.out.println("First value: " + data[0]);
        } catch (IOException e) {
            // recover from a file/network problem
            System.err.println("Could not read file: " + e.getMessage());
        } catch (ArrayIndexOutOfBoundsException e) {
            // recover from a logic problem with the data
            System.err.println("File was empty: " + e.getMessage());
        } finally {
            // always runs — clean up resources here
            System.out.println("Processing finished.");
        }
    }
}

Best practices to keep handling robust:

  • Catch the most specific exception first. Ordering a broad catch (Exception e) before a specific one is a compile error in Java.
  • Never leave a catch block empty. Silently swallowing an exception hides bugs; at minimum log it.
  • Prefer try-with-resources for anything that implements AutoCloseable, so streams and connections close automatically.
  • Do not catch Throwable or Error just to keep the program alive — you will mask fatal conditions.

Error vs Defect vs Bug vs Failure

Outside of Java, the word "error" also has a specific meaning in software testing terminology, and it is easy to confuse it with a programming Error. In testing, these four terms describe distinct stages of how a problem appears:

  • Error — a human mistake. A developer misunderstands a requirement or mistypes logic. The error is the action that introduces the problem.
  • Defect (Bug) — the flaw in the code that the error produces. "Defect" and "bug" are used interchangeably; it is the discrepancy between expected and actual behavior sitting in the source.
  • Fault — sometimes used as a synonym for defect; the incorrect step, process, or data definition in the program.
  • Failure — the visible, external symptom an end user experiences when defective code executes and the system behaves incorrectly.

So a tester might say: a developer's error created a defect (bug) in the code, which caused a failure in production. To dive deeper into classification, see our guide on the different types of bugs in software testing.

Common Mistakes and Troubleshooting

  • Catching Error or Throwable. Wrapping code in catch (Throwable t) to "stay alive" traps OutOfMemoryError and other fatal conditions, leaving the app in a corrupt state. Catch Exception at most.
  • Swallowing exceptions. An empty catch block discards the stack trace and makes failures invisible. Always log, rethrow, or handle meaningfully.
  • Catching the broadest type too early. Putting catch (Exception e) above a specific catch makes the specific block unreachable — a compile error in Java.
  • Confusing OutOfMemoryError with a leak you can catch. You cannot reliably recover from it in a catch; profile the heap and fix the allocation pattern instead.
  • Treating NullPointerException as inevitable. It is an unchecked exception caused by a bug; use Optional, null checks, or Objects.requireNonNull rather than catching it everywhere.

Conclusion

So, what is the difference between an Error and an Exception? An Error is a serious, usually unrecoverable problem from the runtime environment that you should not catch, while an Exception is a recoverable condition in your code or data that you can and should handle with try/catch/finally. Both extend Throwable as siblings, exceptions split into checked and unchecked, and only exceptions belong in your normal error-handling flow. Identify which one you are facing, handle exceptions deliberately, let errors fail fast, and validate that behavior across real environments to ship reliable software.

Frequently Asked Questions

Is an Error a type of Exception in Java?

No. Error and Exception are sibling classes. Both extend the Throwable superclass, but neither extends the other. Error represents serious JVM-level problems, while Exception represents conditions an application can reasonably anticipate and handle.

Can you catch an Error in Java?

Technically yes, because Error extends Throwable, so catch (Throwable t) or catch (Error e) will compile. In practice you should not, because Errors like OutOfMemoryError signal the JVM is in an unrecoverable state and continuing usually causes more damage.

What is the difference between a checked and an unchecked exception?

A checked exception (such as IOException) is verified at compile time and must be caught or declared with throws. An unchecked exception extends RuntimeException, is not enforced by the compiler, and usually signals a programming bug like NullPointerException.

What is the difference between an error and a bug in testing?

In testing terminology, a bug or defect is a flaw a developer introduces in the code, an error is the human mistake that produces that defect, and a failure is the visible incorrect behavior an end user sees when the defective code runs.

Are NullPointerException and OutOfMemoryError the same thing?

No. NullPointerException is an unchecked Exception caused by accessing a null reference in your code, and you can recover from it. OutOfMemoryError is an Error raised by the JVM when heap memory is exhausted, and it is generally not recoverable.

Do errors and exceptions occur at compile time or runtime?

Errors occur only at runtime and cannot be recovered from. Exceptions can surface at either stage: checked exceptions are detected by the compiler at compile time and must be handled or declared, while unchecked exceptions such as NullPointerException appear at runtime when the offending code executes.

Why can't you recover from an Error in Java?

Errors signal that the runtime environment itself is broken, for example the heap is exhausted or the call stack is full. Because the JVM is already in an abnormal state, catching the Error and continuing usually leads to further corruption, so the safe response is to let the application terminate and fix the root cause.

Related Questions

Test Your Website on 3000+ Browsers

Get 100 minutes of automation test minutes FREE!!

Test Now...

KaneAI - Testing Assistant

World’s first AI-Native E2E testing agent.

...

TestMu AI forEnterprise

Get access to solutions built on Enterprise
grade security, privacy, & compliance

  • Advanced access controls
  • Advanced data retention rules
  • Advanced Local Testing
  • Premium Support options
  • Early access to beta features
  • Private Slack Channel
  • Unlimited Manual Accessibility DevTools Tests