IllegalArgumentException, explained and fixed

IllegalArgumentException is thrown deliberately, by a method that examined an argument and rejected it: a negative size, an empty string where content is required, a number outside a documented range, a malformed identifier. Unlike most exceptions on this site, nobody's environment is broken; the library is reporting a contract violation by its caller. The stack trace's top frames name the method that rejected the value, and the message usually states the rule, so the fix is to find which argument, on that call, broke which rule.

How to find the argument

  1. Read the message first: messages like “bound must be positive”, “Illegal character in hostname”, or “groupId must not be empty” state the rule directly; match it against the values passed on the failing line.
  2. The throwing frame is the library's, the frame below it is yours: that caller frame is the line to inspect; log or debug the actual argument values there. The value is frequently not what the code assumes (parsed from input, defaulted, or transformed upstream).

Frequent real-world cases

  1. Parsing and formatting: UUID.fromString, enum valueOf with a name that matches no constant (case matters), date/time formatters fed a string in the wrong pattern, Integer.parseInt on empty text (that one is the subclass NumberFormatException).
  2. Ranges and sizes: thread pool and buffer sizes of zero or negative, substring and capacity arguments out of range, probability or percentage values outside 0 to 1 or 0 to 100.
  3. Framework validation: a request parameter, configuration property, or annotation constraint rejecting input at a boundary, working exactly as designed against genuinely bad input.

The fixes, in order

  1. Correct the value at its source: validate user input where it enters, with messages that help the user; the deep library check is a safety net, not the user interface.
  2. When your own API throws it, keep doing so, and document the rule: failing fast with a clear message is the correct design; callers should be able to learn the constraint from the message alone.
  3. Do not catch and swallow it to “make it run”: a rejected argument means the operation did not happen; continuing as if it did corrupts whatever follows. If the argument is legitimately variable, branch before the call.

Common questions

What is the difference between IllegalArgumentException and IllegalStateException? Argument: the caller passed a bad value, wrong regardless of timing. State: the object's current state makes the call inappropriate (already closed, not yet initialized), the arguments may be fine. The distinction points at who is responsible, the input or the lifecycle.

Is NumberFormatException related? It extends IllegalArgumentException; parsing text into a number is argument validation. The remedies are the same: check the input before or handle the rejection where the text originates.

Should my code throw it or return an error? For programming errors (a caller violating a documented contract), throwing is right, it should be fixed in development. For expected user-input problems, validate earlier and report in the interface, reserving the exception for cases that slip through.

Related errors

NullPointerException · ArrayIndexOutOfBoundsException · Python ValueError: invalid literal