Fix Common Errors

Fix NullPointerException in Java

NullPointerException is Java's classic crash. Learn to read the stack trace, find the null reference, and prevent it with Optional and null checks.

NullPointerException is Java's most notorious runtime error. It crashes your application when code tries to call a method or access a property on a null reference — and because Java makes no distinction between the thousands of ways a variable can be null, the stack trace often points at a line with multiple possible culprits. This guide teaches you to read the trace, hunt down the null reference, and fix it fast.

NullPointerException (often abbreviated NPE) is so common that many Java developers assume it's just the cost of doing business. It doesn't have to be. With the right defensive patterns and proper error tracking in production, you can catch NPEs before they hit users and prevent them from happening in the first place.

What NullPointerException actually tells you

A NullPointerException means your code tried to call a method or read a property (via a field access or array index) on a null value. The exception itself is simple — it's always the same class — but the stack trace is your map to the culprit.

public class UserService {
  public String getUserCity(User user) {
    return user.getAddress().getCity(); // NPE if user or address is null
  }
}

If user is null, you get:

java.lang.NullPointerException
  at UserService.getUserCity(UserService.java:5)

The line number points at the exact line that threw it. But here's the trap: line 5 has three possible null values (user, the result of getAddress(), or the result of getCity()). The stack trace doesn't say which one was null — you have to reason through it. This is where most Java developers lose time.

How to read the stack trace and find the culprit

The stack trace alone won't tell you which dereference was null, but breadcrumbs and context will. In production, you need an error tracker that captures the state leading up to the crash.

When you see an NPE, ask yourself:

  1. What line threw it? Read the top frame of the stack trace.
  2. What dereferences happen on that line? Count them: user (reference), .getAddress() (return value), .getCity() (return value).
  3. What is the state before this call? This is where logging and error tracking save you hours. Breadcrumbs show you what the user did, what values were passed in, and what prior requests succeeded or failed.
// Example with more context:
public class OrderService {
  public void processOrder(Order order) {
    User user = order.getUser();
    String city = user.getAddress().getCity(); // Line 50 — NPE here
  }
}

If order.getUser() returned null, the NPE is on line 50, but the real bug is one line up — you didn't check if getUser() was null before using it.

Modern Java stack traces in Java 14+ include a helpful arrow showing exactly which dereference failed: NullPointerException: Cannot invoke method 'getCity()' because 'user.address' is null. Earlier versions don't include this — you have to read the line and deduce it.

Common causes in production Java apps

Most NPEs in production fall into a few patterns:

API responses returning unexpected shapes. A REST endpoint returns partial data and a downstream service assumes all fields exist.

Methods returning null instead of empty collections. A DAO method returns null instead of an empty List, and calling code iterates without checking:

List<Order> orders = orderDao.findByUser(userId); // returns null sometimes
for (Order order : orders) { // NPE here
  processOrder(order);
}

Cascade of null checks forgotten. In a long chain like user.getProfile().getSettings().getTheme(), any intermediate step can be null.

Optional values not unwrapped safely. Passing an Optional to code that expects a non-null value, or forgetting to call orElse():

Optional<User> user = findUser(id);
String city = user.getAddress().getCity(); // wrong — Optional is not a User

Race conditions and lazy initialization. A field is lazily initialized but accessed before initialization completes in a multithreaded context.

Preventing NullPointerException: Best practices

Use Optional for values that can be absent

Java's Optional type makes absence explicit and forces you to handle it:

Optional<User> user = findUser(id);
String city = user
  .map(User::getAddress)
  .map(Address::getCity)
  .orElse("Unknown");

This chains safely — if any intermediate step is empty, the result is "Unknown", with no NPE.

Validate inputs at the boundary

Check for null at entry points — REST controllers, service methods, listeners. Fail early and loudly:

public User createUser(CreateUserRequest request) {
  if (request == null) {
    throw new IllegalArgumentException("request cannot be null");
  }
  if (request.getEmail() == null || request.getEmail().isEmpty()) {
    throw new IllegalArgumentException("email is required");
  }
  // ... proceed safely
}

Return empty collections, not null

A method that returns a list should always return a List, even if empty:

// Bad
public List<Order> findByUser(String userId) {
  if (userId == null) return null; // caller must check for null
}

// Good
public List<Order> findByUser(String userId) {
  if (userId == null) return Collections.emptyList();
}

Now calling code never needs to null-check the result.

Use annotations for clarity

Tools like @Nullable and @NonNull (from IDE support or libraries like Checker Framework) signal intent:

public String getCity(@NonNull User user) {
  return user.getAddress().getCity(); // IDE warns if you pass null
}

Your IDE and linters will catch unsafe calls before you deploy.

Finding NPEs in production

Even with defensive programming, NPEs slip through to production. When they do, error tracking is the fastest way to diagnose and fix them. An error tracker captures:

  • The exact stack trace and line number
  • The breadcrumb trail — what the user did, what requests fired, what exceptions happened before the crash
  • The affected user and session
  • The release that introduced the regression

Instead of guessing why user.address was null, you see the logs leading up to the crash and can reproduce the exact path. For deeper investigation patterns, see how to debug production errors.

In Spring Boot, configure your error tracker to tag releases so you can pinpoint which deploy introduced the NPE. See release health monitoring for the full strategy.

Catching NPEs across your Java stack

If you're running Spring Boot, Spring Boot error tracking walks through wiring up the Sentry SDK to capture uncaught exceptions automatically. For any Java application, the setup is the same: initialize the SDK once at startup, and every NPE gets captured with full context.

Start tracking errors in minutes

Stop chasing NullPointerExceptions in production logs. LightTrace captures the stack trace, breadcrumbs, and affected user for every NPE — start free and see the full story behind your Java crashes.

With automatic capture, clear stack traces, and full context, NullPointerException stops being a mysterious crash and becomes a one-liner fix.

Fix your next production error faster

Point any Sentry SDK at LightTrace — free up to 5,000 events/month.