NullPointerException, explained and fixed

A NullPointerException (NPE) is thrown when code uses a reference that holds null as if it pointed at an object: invoking a method on it, reading or writing a field, indexing it as an array, or unboxing it into a primitive. Since Java 14, the message usually names the exact expression that was null, for example “Cannot invoke "String.length()" because "name" is null”, which turns most occurrences into a short investigation: where was that variable supposed to be assigned?

How to find the source

  1. Read the message literally on Java 14 and later; it identifies the null expression precisely. On older versions, use the top stack frame's line number and identify every reference used on that line; one of them is null.
  2. Walk the value backwards: was it a method's return value (methods that return null on “not found” are the top source, map lookups, finders, parsers), a field never initialized, a parameter the caller passed as null, or the result of a chained call whose middle step returned null?

The usual causes, most common first

  1. Lookups that miss: map.get(key) for an absent key, a repository or finder returning null for “no such record”, getParameter for a missing request parameter.
  2. Chained calls with a nullable middle: order.getCustomer().getAddress() where the customer exists but the address does not.
  3. Unboxing a null wrapper: an Integer or Boolean that is null converted to int/boolean, in a return statement, arithmetic, or a ternary, often far from where the null originated.
  4. Fields initialized in a different lifecycle: dependency injection that did not run for a manually constructed object, a setup method that a test or a code path skipped, an array created but never filled (its elements are null).
  5. Autoboxed comparisons and switch statements over a null enum or string.

The fixes, matched to the cause

  1. Fix the contract where null is not a legal answer: if a method must always produce a value, make it throw a meaningful exception or return an empty collection instead of null; collections in particular should almost never be null, empty is the correct “nothing”.
  2. Use Optional for genuinely optional results from your own APIs, so callers are forced by the type to handle absence; and check Map lookups with getOrDefault or containsKey when a key may be absent.
  3. Fail fast at boundaries: Objects.requireNonNull(arg, "arg") at public entry points turns a confusing deep NPE into an immediate, named failure at the caller, where the mistake actually is.
  4. Guard where absence is legitimate, with an explicit null check whose branch does something sensible (a default, a skip, a user-facing “not found”), rather than letting the exception serve as control flow.
Annotating everything nullable does not fix code, and neither does wrapping whole methods in try-catch for NPE. The durable work is deciding, per value, whether null is a legal state, encoding that in the type or the contract, and handling it exactly where it can occur.

Common questions

Why does my older Java not show which variable was null? Helpful NPE messages arrived in Java 14 (JEP 358) and are on by default from Java 15. On older runtimes the stack trace and line number are all you get, and a debugger or logging at the line is the way to identify the null reference.

What does “because the return value of ... is null” mean? A method in the chain returned null and the next operation dereferenced it. The named method is the producer to inspect; its contract either allows null (handle it) or has a bug (fix it).

Is Optional the answer to all NPEs? No. Optional suits return values of your own methods. It does not help with fields, parameters, or third-party APIs, and using it for those creates awkward code. Contracts and boundary checks cover the rest.

Related errors

ArrayIndexOutOfBoundsException · IllegalArgumentException · StackOverflowError