Skip to content

Fix: Java java.lang.IllegalArgumentException

FixDevs ·

Quick Answer

How to fix Java IllegalArgumentException caused by null arguments, invalid enum values, negative numbers, wrong format strings, and Spring/Hibernate validation failures.

The Error

Your Java application throws:

java.lang.IllegalArgumentException: argument type mismatch

Or variations:

java.lang.IllegalArgumentException: No enum constant com.example.Status.UNKNOWN
java.lang.IllegalArgumentException: Invalid character found in method name
java.lang.IllegalArgumentException: Comparison method violates its general contract!
java.lang.IllegalArgumentException: bound must be positive
java.lang.IllegalArgumentException: Name for argument of type [java.lang.String] not specified

A method received an argument that is not valid according to its contract. The argument has the correct type (it compiled), but its value is not acceptable.

Why This Happens

IllegalArgumentException is thrown when a method receives an argument that fails a precondition check. Unlike NullPointerException (which is unintentional), IllegalArgumentException is explicitly thrown by code that validates its inputs.

Common causes:

  • Null passed where non-null is required. A method explicitly rejects null.
  • Out-of-range value. A negative number where only positives are allowed.
  • Invalid enum name. Enum.valueOf() with a string that does not match any constant.
  • Format mismatch. A date string that does not match the expected pattern.
  • Comparator contract violation. A Comparator that is not transitive or consistent.
  • Reflection argument mismatch. Calling a method via reflection with wrong argument types.
  • Spring/Hibernate validation. Framework-level validation rejects input values.

Fix 1: Validate Arguments Before Passing

Check the value before calling the method:

Broken — passing invalid value:

// Random.nextInt(bound) requires bound > 0
Random random = new Random();
int result = random.nextInt(0);  // IllegalArgumentException: bound must be positive

Fixed:

Random random = new Random();
int bound = getBound();
if (bound <= 0) {
    throw new IllegalArgumentException("Bound must be positive, got: " + bound);
    // or use a default
    bound = 1;
}
int result = random.nextInt(bound);

Common methods that throw IllegalArgumentException:

MethodRequirement
Random.nextInt(bound)bound > 0
String.substring(begin, end)0 ≤ begin ≤ end ≤ length
Arrays.copyOfRange(arr, from, to)from ≤ to
Collections.nCopies(n, obj)n ≥ 0
Thread.sleep(millis)millis ≥ 0

Pro Tip: When you get an IllegalArgumentException, read the message carefully. It usually tells you exactly what is wrong with the argument. The fix is almost always to validate the value before passing it to the method.

Fix 2: Fix Enum.valueOf() Errors

Enum.valueOf() throws IllegalArgumentException when the string does not match any constant:

Broken:

enum Status { ACTIVE, INACTIVE, PENDING }

String input = "UNKNOWN";
Status status = Status.valueOf(input);
// IllegalArgumentException: No enum constant Status.UNKNOWN

Fixed — handle unknown values:

// Option 1: Try-catch
try {
    Status status = Status.valueOf(input.toUpperCase());
} catch (IllegalArgumentException e) {
    Status status = Status.PENDING;  // Default value
}

// Option 2: Custom lookup method
public static Status fromString(String value) {
    for (Status s : Status.values()) {
        if (s.name().equalsIgnoreCase(value)) {
            return s;
        }
    }
    return Status.PENDING;  // Default
}

// Option 3: Use a Map for O(1) lookup
private static final Map<String, Status> LOOKUP = Arrays.stream(Status.values())
    .collect(Collectors.toMap(Enum::name, Function.identity()));

public static Optional<Status> fromString(String value) {
    return Optional.ofNullable(LOOKUP.get(value.toUpperCase()));
}

Jackson/JSON deserialization:

@JsonCreator
public static Status fromJson(String value) {
    return Arrays.stream(Status.values())
        .filter(s -> s.name().equalsIgnoreCase(value))
        .findFirst()
        .orElse(Status.PENDING);
}

Common Mistake: Assuming user input will always match an enum constant exactly. Enum names are case-sensitive (ACTIVEactive). Always normalize the input (.toUpperCase()) or use case-insensitive comparison.

Fix 3: Fix Comparator Contract Violations

The error “Comparison method violates its general contract” means your Comparator is not transitive:

Broken:

// Inconsistent comparator — violates transitivity
list.sort((a, b) -> {
    if (a.getScore() > b.getScore()) return 1;
    if (a.getScore() < b.getScore()) return -1;
    return 0;  // Might not handle NaN or null correctly
});

Broken — comparing doubles with floating-point issues:

list.sort((a, b) -> (int)(a.getPrice() - b.getPrice()));
// Casting to int loses precision: 0.5 - 0.3 = 0.2, (int)0.2 = 0 (treated as equal)

Fixed — use built-in comparators:

// For primitives
list.sort(Comparator.comparingInt(Item::getScore));
list.sort(Comparator.comparingDouble(Item::getPrice));

// Multiple fields
list.sort(Comparator.comparing(Item::getCategory)
    .thenComparingDouble(Item::getPrice)
    .thenComparing(Item::getName));

// With null handling
list.sort(Comparator.comparing(Item::getName, Comparator.nullsLast(Comparator.naturalOrder())));

Fixed — use Double.compare() for doubles:

list.sort((a, b) -> Double.compare(a.getPrice(), b.getPrice()));

Fix 4: Fix Reflection Argument Mismatches

Calling methods via reflection with wrong argument types:

Broken:

Method method = MyClass.class.getMethod("process", int.class);
method.invoke(obj, "hello");  // IllegalArgumentException: argument type mismatch

Fixed — match the parameter types:

Method method = MyClass.class.getMethod("process", int.class);
method.invoke(obj, 42);  // Correct type

// For primitive vs wrapper issues:
Method method = MyClass.class.getMethod("process", Integer.class);  // Use Integer, not int
method.invoke(obj, Integer.valueOf(42));

Check parameter types before invoking:

Method method = MyClass.class.getMethod("process", int.class);
Class<?>[] paramTypes = method.getParameterTypes();
System.out.println(Arrays.toString(paramTypes));  // [int]

Fix 5: Fix Date and Time Parsing

Invalid date/time formats cause IllegalArgumentException:

Broken:

// Wrong format
LocalDate date = LocalDate.parse("03/15/2024");
// IllegalArgumentException (or DateTimeParseException which extends it)

// Wrong value
LocalDate date = LocalDate.of(2024, 13, 1);  // Month 13 doesn't exist

Fixed:

// Specify the format
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MM/dd/yyyy");
LocalDate date = LocalDate.parse("03/15/2024", formatter);

// Validate before parsing
public static Optional<LocalDate> parseDate(String input, String pattern) {
    try {
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern);
        return Optional.of(LocalDate.parse(input, formatter));
    } catch (DateTimeParseException e) {
        return Optional.empty();
    }
}

Fix 6: Fix Spring Framework Errors

Spring commonly throws IllegalArgumentException for configuration issues:

Missing request parameter:

IllegalArgumentException: Name for argument of type [java.lang.String] not specified

Fixed — use @RequestParam with name:

@GetMapping("/search")
public ResponseEntity<List<Item>> search(@RequestParam("q") String query) {
    return ResponseEntity.ok(service.search(query));
}

Bean validation errors:

@PostMapping("/users")
public ResponseEntity<User> create(@Valid @RequestBody UserRequest request) {
    // @Valid triggers bean validation
    // If validation fails, MethodArgumentNotValidException is thrown
}

public record UserRequest(
    @NotBlank String name,
    @Email String email,
    @Min(0) @Max(150) int age
) {}

Property resolution:

IllegalArgumentException: Could not resolve placeholder 'api.key' in value "${api.key}"

Fixed — add the property or provide a default:

@Value("${api.key:default-value}")
private String apiKey;

Or add it to application.properties:

api.key=your-key-here

Fix 7: Fix Collection and Array Operations

Arrays.asList() with primitives:

int[] numbers = {1, 2, 3};
List<int[]> list = Arrays.asList(numbers);  // Creates a List of one int[] element!

// Fixed — use Integer[]
Integer[] numbers = {1, 2, 3};
List<Integer> list = Arrays.asList(numbers);

// Or use streams
List<Integer> list = Arrays.stream(new int[]{1, 2, 3}).boxed().toList();

Collections.unmodifiableList() modifications:

List<String> immutable = Collections.unmodifiableList(original);
immutable.add("new");  // UnsupportedOperationException, not IllegalArgumentException
// But some operations throw IllegalArgumentException

Map.of() with duplicate keys:

Map<String, Integer> map = Map.of("a", 1, "a", 2);
// IllegalArgumentException: duplicate key: a

Fix 8: Write Defensive Methods

Add argument validation to your own methods:

public class UserService {

    public User createUser(String name, String email, int age) {
        // Java's Objects utility
        Objects.requireNonNull(name, "name must not be null");
        Objects.requireNonNull(email, "email must not be null");

        // Custom validation
        if (name.isBlank()) {
            throw new IllegalArgumentException("name must not be blank");
        }
        if (age < 0 || age > 150) {
            throw new IllegalArgumentException("age must be between 0 and 150, got: " + age);
        }
        if (!email.contains("@")) {
            throw new IllegalArgumentException("invalid email: " + email);
        }

        return new User(name, email, age);
    }
}

Using Guava Preconditions:

import com.google.common.base.Preconditions;

public void transfer(Account from, Account to, BigDecimal amount) {
    Preconditions.checkNotNull(from, "from account must not be null");
    Preconditions.checkNotNull(to, "to account must not be null");
    Preconditions.checkArgument(amount.compareTo(BigDecimal.ZERO) > 0,
        "amount must be positive, got: %s", amount);
}

Still Not Working?

Check the full stack trace. The exception message and the stack trace tell you which method threw the exception and what argument was invalid.

Check for version mismatches. Library upgrades can change validation rules. A method that accepted null in v1 might reject it in v2.

Check for thread safety. Concurrent access to non-thread-safe collections (HashMap, ArrayList) can cause IllegalArgumentException with confusing messages like “Comparison method violates its general contract.”

For Java null pointer errors, see Fix: Java NullPointerException. For class loading issues, see Fix: Java ClassNotFoundException. For Spring Boot startup errors, see Fix: Spring BeanCreationException.

F

FixDevs

Solo developer based in Japan. Every solution is cross-referenced with official documentation and tested before publishing.

Was this article helpful?

Related Articles