18

Let's start with the Javadocs:

IllegalStateException

Signals that a method has been invoked at an illegal or inappropriate time. In other words, the Java environment or Java application is not in an appropriate state for the requested operation.

IllegalArgumentException

Thrown to indicate that a method has been passed an illegal or inappropriate argument.

The problem with the above is that they are very black and white. Consider a use case where a method is parsing a file provided by the caller. The file exists, is readable, and is in the correct format. However, some content in the file is non-compliant with the business rules. What would be an appropriate exception to throw in this case - IllegalStateException or IllegalArgumentException?

Looking at various libraries that provide assertions, like Guava Preconditions or Spring Assert, it appears that there is no consensus. There are some good discussions here and here, but none provide a conclusive answer to the common use case I stated above.

E_net4
  • 27,810
  • 13
  • 101
  • 139
Abhijit Sarkar
  • 21,927
  • 20
  • 110
  • 219
  • 1
    I'm sorry, but there is no correct answer to this. The "right" way to do it is a matter of opinion ... as clearly illustrated by the contradictory answers below and the unseemly downvoting patterns. Clearly, there is no "conclusive" answer. – Stephen C Feb 12 '18 at 01:25
  • 1
    (FWIW, my opinion is "neither" ... in this case. But I agree with the people who said that these two exceptions refer to orthogonal things. One is about the arguments that were passed. The other is about the state of the target object (not the arguments) when the call was made. The distinction is clear cut.) – Stephen C Feb 12 '18 at 01:27

5 Answers5

11

Putting in other words:

The IllegalArgumentException is thrown in cases where the type is accepted but not the value, like expecting positive numbers and you give negative numbers.

The IllegalStateException is thrown when a method is called when it shouldn't, like calling a method from a dead thread.

I don't see how they could mix. In your question about the file with problems, I think that throwing either a ParseException or an IOException would be more appropriate.

Saclyr Barlonium
  • 453
  • 4
  • 12
  • *"I think that throwing either a ParseException or an IOException would be more appropriate"* +1 to that – MadProgrammer Feb 11 '18 at 21:11
  • 2
    It's certainly not an `IOException` because there's nothing wrong with an IO operation. IMO, most Java libraries abuse `IOException`. What is the `ParseException` that you referred to - JDK 8 has no such thing as [RuntimeException](https://docs.oracle.com/javase/8/docs/api/java/lang/RuntimeException.html). – Abhijit Sarkar Feb 11 '18 at 21:12
  • @AbhijitSarkar [`java.text.ParseException`](https://docs.oracle.com/javase/8/docs/api/java/text/ParseException.html) – MadProgrammer Feb 11 '18 at 21:15
  • For the ParseException in JDK8 see: https://docs.oracle.com/javase/8/docs/api/index.html?java/text/ParseException.html – Saclyr Barlonium Feb 11 '18 at 21:15
  • @AbhijitSarkar, you are probably right, IOException is probably not a very good use for the given example. I just thought that since it's a problem reading a file, it should throw an exception linked with reading files. The ParserException seems a better choice. – Saclyr Barlonium Feb 11 '18 at 21:29
  • The state of a component can change which inputs are valid. e.g. say you can only provide a number which is larger than one provided before. Such cases are rare. – Peter Lawrey Feb 11 '18 at 22:12
  • @PeterLawrey Do you mean cases where `IllegalStateException` is appropriate are rare? Also, how's your comment related to this answer. Please elaborate. – Abhijit Sarkar Feb 11 '18 at 22:14
  • @AbhijitSarkar I mean there are cases there the state determines what is invalid so you could throw either. – Peter Lawrey Feb 11 '18 at 22:21
  • 1
    OK, `ParseException` seemed promising on the surface, but after looking at the Javadoc, it appears that it's intended to be used with streaming parsers. The constructor takes an offset, which I don't think I want to track. I'm leaning towards subclassing [IllegalFormatException](https://docs.oracle.com/javase/8/docs/api/java/util/IllegalFormatException.html). – Abhijit Sarkar Feb 11 '18 at 22:25
  • 2
    @MadProgrammer, I would definitely advise against `IOException` as there is nothing wrong with IO operations but not sure about `ParseException`. Subclasses of `IllegalFormatException` is a better choice, I guess – Farid Oct 08 '19 at 10:01
6

IllegalStateException is for coding errors, not input errors. It's for when the invariants of a class have been violated, or a method is called when an object is in the wrong state. Examples are using a closed resource, or closing a resource twice.

IllegalArgumentException is when an argument has an invalid value per the method API. Passing -1 when only positive numbers are allowed.

In this case neither exception is appropriate. I would create a sub-class of IOException since there's an error in an input file.

John Kugelman
  • 349,597
  • 67
  • 533
  • 578
  • 1
    IMHO I don't think it's necessary to extend `IOException`, as the issue isn't with the file, but with parsing the file, `ParseException` would be more appropriate – MadProgrammer Feb 11 '18 at 21:23
  • I agree to @MadProgrammer , `IOException`s signal that io operations failed which is not the case. Additionally, the use case's file is well formatterd, so i would not use `ParseException` because it will signal to the developer that the format is invalid, instead of signalling that the business rules are violated. – sn42 Feb 11 '18 at 22:41
  • Let's say `userId` is being used as parameter in a request to do some operations depending on it. Which one of these exceptions should be thrown if no users exist in db with that userId ? – Clay May 22 '23 at 15:44
5

The other answers highlight when to use IllegalArgumentException or IllegalStateException. But in my view (note: opinion based) these exceptions should not be used in your use case.

To summarize: Some file contains data in a valid format, is successfully loaded into the application but some values are not compliant to your business rules (Note: No IO operations failed, the format is valid => neither IOException nor ParseException should be used, they indicate failed IO operations or invalid formats).

Why you should not use IllegalArgumentException?

This exception is thrown to indicate that a method has been passed an illegal or inappropriate argument. You could argue that you have a method validating the file and the value of a field or the combinations of values of several fields in this file are illegal or non-compliant to your business rules. Yepp, point to you. But if you throw an IllegalArgumentException in this situation you can not separate IllegalArgumentExceptions caused by other libraries (or the standard library or from your own code somewhere else) and the IllegalArgumentExceptions from your validator which indicate a business rule violation easily (sure, you could subclass IAE and catch it in a calling method).

Why do you want to separate these exceptions? Use case: Business rule violations should be presented to the user so he can change his non-compliant inputs. Other IAE's or general any uncatched runtime exception indicates that the request failed on the server for example. In these cases you have to send different responses to clients.


You can argue in a similar way why IllegalStateExceptions should not be used to indicate business rule violations. So, what should be used in your use case? This depends highly on the scale of your application. Some custom subclass of RuntimeException may do the Job for small applications. For larger applications validation libraries like "javax.validation" are worth a try.

luk2302
  • 55,258
  • 23
  • 97
  • 137
sn42
  • 2,353
  • 1
  • 15
  • 27
  • Your answer explains a few nuances quite well, but at the same time looks much like thorough research without a single word in conclusion. I mean the OP is already in confusion to choose among the exception types. I believe, stating your opinion based on the use case of OP would make it more like an answer than an extension to the question )) – Farid Oct 08 '19 at 09:55
-1

Consider a use case where...

And if those were the only two options I had, in your use-case, I'd lean towards IllegalStateException

Why? Because the argument's are valid, they point to a file, which can be read. It's not the argument that is invalid, it's the fact that parsing the file would invalid the state.

This of course assumes that IllegalStateException and IllegalArgumentException are the only exceptions you are considering.

This is course just MHO. I think the important aspect is, you can define the reasons for using one exception over another in a consistent way which makes your API understandable.

I also agree with Saclyr (+1 to their answer), there are more appropriate exceptions you could use to define why the method call failed (personally, I'd consider java.text.ParserException)

MadProgrammer
  • 343,457
  • 22
  • 230
  • 366
  • 1
    `IllegalStateException` is for when the state is already invalid, not when it *would* be invalidated. An external file is not application state, so this would be a misleading exception IMO. – John Kugelman Feb 11 '18 at 21:16
  • @JohnKugelman I'm not disagreeing with, I was focused on the if-or condition of the question - there are more appropriate exceptions which could be used. IMHO I still think it provides an opportunity to describe a situation where applying the properties would invalidate the state of the object, but where the input/argument itself is valid. Rather then taking the concept as "written in stone", I've interrupted the intent based on the available input. For me, neither are appropriate for the use case, as I've stated – MadProgrammer Feb 11 '18 at 21:19
-1

I also think that the two methods have a very close semantic.

According to the IllegalArgumentException javadoc, passing an invalid argument may be handled by throwing IllegalArgumentException :

Thrown to indicate that a method has been passed an illegal or inappropriate argument.

But invoking a method with a bad argument may also be handled by throwing IllegalStateException as its javadoc states that :

Signals that a method has been invoked at an illegal or inappropriate time.

Indeed, invoking a method with an inappropriate or illegal argument may also mean that the method was invoked at an illegal or inappropriate time.

To make simple, I think that IllegalArgumentException and IllegalStateException may be used in a interchangeable way by some developers as the issue is caused by the passed argument(s). What I explained above.
While IllegalStateException use cases that are not related to a passed argument have not to be interchanged with IllegalArgumentException.

The nuance being slight, most of libraries mix sometimes their usage.

I am afraid to not be able to give you a more solid explanation. Semantic is semantic and as two things may be interpreted in a closer way, it is often not clearly used.

davidxxx
  • 125,838
  • 23
  • 214
  • 215
  • @Downvoter If you downvote tautologies, do you also upvote self contradictions? If So many third party libraries use them in a different way, it is not only chance. – davidxxx Feb 11 '18 at 22:01
  • I didn't downvote you, but I might consider it. Your answer adds nothing to what's already stated in my question. It shouldn't be posted as an answer. – Abhijit Sarkar Feb 11 '18 at 22:17
  • "Your answer adds nothing" I go into your way but I adds a thing that I think important : I explain why these exceptions are sometimes used in an interchangeable way. – davidxxx Feb 11 '18 at 22:45