Ant: A Case Study in How Not To Write An Error Message

After I complained about about build failures in Ant 1.6 on Cafe au Lait, a couple of Ant developers wrote to me with various suggestions and FAQ references. They were nothing I hadn’t tried before though, and didn’t explain why I could make the build work with Ant 1.5 and not Ant 1.6. However what really annoyed me about this whole situation was not the bug. It was the lazy error message.

Here’s the original post:

The Apache Project has released version 1.6.3 of Ant, the popular open source build tool. Version 1.6.3 is a bug fix release. However it still hasn’t fixed the bug that makes the test target in XOM die, even though it runs just fine in 1.5.4. The error message claims:

BUILD FAILED
/Users/elharo/Projects/XOM/build.xml:496: 
Could not create task or type of type: junit.

Ant could not find the task or a class this task relies upon.

This is then followed by a lot of obnoxious verbiage about what could possibly be going wrong (half of which hasn’t been true for at least two major releases) and a warning not to bother the Ant developers with this because they’re sick of hearing from lusers like me. (Well, the message isn’t quite that obnoxious, but it’s close.)

Word to the Ant team: WAKE UP! You keep getting bug reports about the junit task because it’s buggy. At absolute best, it’s confusing and poorly designed. That’s a bug. You need to fix it.

But even allowing for the poor design and the user errors that causes, there are still some cases here where the junit task simply does not do what it claims to do despite the user doing exactly what they’re supposed to do. I suspect ClassLoader issues, possibly involving multiple copies of JUnit, one in the user’s CLASSPATH and one in Ant’s lib directory. Ant does some really skanky things with multiple class loaders, and I know that’s hard to debug and harder to test, but it still needs to be done. As a Google search on this error message will prove, many users are tripping all over the bugs in the junit task; and have been for a long time now. The first step to recovery is admitting you have a problem.

However what really gets my goat about this whole situation is not the bug. It’s the lazy error message. Let’s deconstruct it, paragraph by paragraph:

BUILD FAILED
/Users/elharo/Projects/XOM/build.xml:496: 
  Could not create task or type of type: junit.

OK. This much is good. It tells me what task failed and on what line the problem occurred so I can find it and fix it.

Ant could not find the task or a class this task relies upon.

Now things start to fall apart. Why “the task or a class this task relies upon”? Presumably Ant knows which task or class it couldn’t find. Be specific. Give me the actual name. If it was a NoClassDefFoundError, give me the name of the class. Don’t tell me it might be one of these or it might be one of those. Tell me what the problem really was!

This is common and has a number of causes; the usual 
solutions are to read the manual pages then download and
install needed JAR files, or fix the build file:

I can well believe the problem is common. But why tell me about “a number of causes”? Tell me what the cause really is.

 - You have misspelt 'junit'.
   Fix: check your spelling.

No, I haven’t. What’s more Ant knows I haven’t, or at least it should. junit is a standard Ant task, shipped with Ant 1.6 by default. Ant should recognize this and not bother me about the spelling of something that’s correct. Now if I spelled it ‘jnuit’ or ‘JUnit’ then there’s a problem, and it should tell me that. It could then further suggest that I might have meant ‘junit’. However, don’t tell me the problem might be a spelling error when it clearly isn’t.

 - The task needs an external JAR file to execute
     and this is not found at the right place in the classpath.
   Fix: check the documentation for dependencies.
   Fix: declare the task.

OK, this one’s possible, but again the message is not precise enough. Either a JAR file is missing or it isn’t. If it’s missing, then tell me which JAR file is missing. Don’t make me guess.

 - The task is an Ant optional task and the JAR file and/or libraries
     implementing the functionality were not found at the time you
     yourself built your installation of Ant from the Ant sources.
   Fix: Look in the ANT_HOME/lib for the 'ant-' JAR corresponding to the
     task and make sure it contains more than merely a META-INF/MANIFEST.MF.
     If all it contains is the manifest, then rebuild Ant with the needed
     libraries present in ${ant.home}/lib/optional/ , or alternatively,
     download a pre-built release version from apache.org

This one’s not possible, and Ant should know that. In this case Ant itself can look in my lib/ant-junit.jar file and tell that it contains the right files. So why is it bothering me about this very unlikely case? Of course, if it looks in that file and it sees it only contains the manifest, then this error message would be appropriate. Otherwise it should shut up about it.

 - The build file was written for a later version of Ant
   Fix: upgrade to at least the latest release version of Ant

Actually it’s exactly the opposite problem. My build file works fine in 1.5. It fails in 1.6. Either way, Ant should figure this out. It should be able to determine if the problem is a version mismatch or not. If it is, then be more specific about the statements causing the trouble. If it isn’t, don’t even mention this.

 - The task is not an Ant core or optional task 
     and needs to be declared using <taskdef>.

Again Ant should know better. It should recognize the names of the core and optional tasks. This might be a reasonable message if I am indeed trying to use a custom task. It is not a reasonable message when the task is something as standard as ‘junit’.

 - You are attempting to use a task defined using 
    <presetdef> or <macrodef> but have spelt wrong or not 
   defined it at the point of use

Unlikely, as I’ve never actually heard of these options. Ant should be smart enough to see that there are no <presetdef> or <macrodef> elements anywhere in my build.xml, and therefore not bother me with this spurious message.

Remember that for JAR files to be visible to Ant tasks implemented
in ANT_HOME/lib, the files must be in the same directory or on the
classpath

This one might really be relevant to me. A lot of the documentation the developers keep referring me to seems to say it is. However, none of the solutions listed there (putting junit.jar in $ANT_HOME/lib, etc.) actually work.

Please neither file bug reports on this problem, nor email the
Ant mailing lists, until all of these causes have been explored,
as this is not an Ant bug.

I’m sorry. It is a bug. Even if I’m missing something in this massive error message that points me at exactly how to make this work, it’s still buggy. Presenting over half a dozen different possible sources of the problem is wrong. There is one problem, and that is what the error message should refer to.

There is some hope that this will be fixed. Steve Loughran tells me, “we have much better diagnostics and reporting on Ant1.7 when classes wont instantiate. Why isnt this in Ant1.6.3: because we dont add changes that break things to point releases. By doing a minor update we ensure that we will be out in next weeks eclipse and netbeans releases, whereas the beta test time and release lag for 1.7 will be many months. If you want to see the new message, download CVS_HEAD and see it for yourself.”

Time will tell. However, this should never have happened in the first place. Developers generally pay far too little attention to error messages. Any error message that will be presented to an end user of the application should be clear, well-written, and accurate. It should give explicit details about the cause of the problem in language that’s relevant to the user. In this case, the user is a Java programmer so it’s OK to use words like “CLASSPATH” and “macrodef”. However, it’s not OK to simply dump a laundry list of everything that might possibly be causing the error. I’m not interested in every possible way this problem could be triggered. I want to know what is triggering it, right here and right now. Obviously there are some unexpected errors that might not be handled perfectly; but this isn’t one of those cases. This is a constant, ongoing bug that bedevils everyone who uses Ant with JUnit, as witnessed by the numerous FAQ entries and mailing list posts on the subject. It’s worth handling better.

21 Responses to “Ant: A Case Study in How Not To Write An Error Message”

  1. kent Says:

    Better error messages

    If a user asks me about an error message, I rewrite the message or change the software so I don’t get the same question again. This practice has served me well – it leads to happier users and a less-annoyed developer 🙂 Too bad the Ant developers don’t work the same way.

  2. magenta Says:

    Ant Rant

    I’m quite intrigued that in your part of the world “April 30, 2005” falls on a Monday. You must be more tired than I am.

    I do agree with what you said – complexity is a bug and the error message is a usability bug. It seems that for most programmers it is only a bug if it blue-screens. Sadly though you only have yourself to blame for the bug. Ant is open source, you can download the code and fix it and then offer the fix back to the ant project. You also have the option to go back to 1.5.4.

    I have to admit that I’m guilty of being one of those developers who “generally pay far too little attention to error messages.”. I’m lucky to have wordsmiths and application specialists to catch error message that make it to the user, but deep down in my debugging code I don’t really care what it says, other than “Oops something happened here, fix it”.

    Pointing out the problem so that others are aware of it is worthwhile, but so is fixing the code. Perhaps your next entry will be on how you fixed the problem.

  3. eriday Says:

    It’s worse than you make it sound.

    If you’re working in Eclipse and have this problem you’ll eventually find http://www.ryanlowe.ca/blog/archives/001038_junit_ant_task_doesnt_work_in_eclipse.php

    Read the comments, people are treating him like a god. I thrashed around for quite a while with this one, and finally went from the message you describe to “…junit.jar is not a directory”. After much more thrashing around, I found that I had multiple junit.jars on my classpath.

    Ant, JUnit, Eclipse are all standards. Eclipse doesn’t use ANTHOME; Ant pretends it doesn’t know how to deal with JUnit. They’re all giving bad error message (can’t blame JUnit, they never got a chance to give a bad error message).

  4. shpxnvzer Says:

    Very Insightful!

    OK, there is obviously a core concept you are missing. You seem to believe that the authors of Ant should have thought up every possible way in which you would break Ant ahead of time (you do realize the possibilities are endless?) and provided some nice, custom, hand holding advice for each and every one. Ok, so the software is not omnipotent. Let’s examine exactly where Ant is making the mistake here.

    “I can well believe the problem is common. But why tell me about “a number of causes”? Tell me what the cause really is.”

    If you would read the lines following that paragraph you would see some examples of exactly what the cause might be. This is apparently a phrase added in order to get you to actually read more than just the first of the potential causes it lists. Looks like, from the rest of your diatribe, it worked. “No, I haven’t. What’s more Ant knows I haven’t, or at least it should.” No, it is telling you that it does not recognize the task. Your confusion is of course understandable given your assumption that every possible error condition is handled with a custom message tailored to your unique situation. In reality, however, Ant does not magically know *how* you misspelled your task, only that it can’t find it. Do you expect it to be able to tell the difference between a misspelled task invocation and one that should be there but is missing? “Either a JAR file is missing or it isn’t. If it’s missing, then tell me which JAR file is missing.” Ah, I see. So, then, you expect that Ant should not only tell you that you are missing some needed jar, but somehow guess as to what the name of the jar is that it can’t find? Ya know, I would expect it to go and find it for you too. Perhaps it should just go ahead and write the task itself, on the fly, and save you the trouble of having to have jars. Now that would be easy to use. “Unlikely, as I’ve never actually heard of these options.” How silly of Ant not to know that you have never heard of these options. Agreed. “However, none of the solutions listed there (putting junit.jar in $ANT_HOME/lib, etc.) actually work.” For you. Let’s see, tens of thousands of developers have no trouble getting it to work. But it must be Ant that’s broken. Right.

    “I’m sorry. It is a bug.” I’m sorry, it’s not a bug. Unless of course having users that don’t understand their software is somehow the developers’ fault. “Even if I’m missing something in this massive error message that points me at exactly how to make this work, it’s still buggy.” Here’s a hint. You are. And it’s in the beginning. But I won’t spoil the fun of letting you figure it out for yourself. Of course, if you get tired of looking you can always go back to make. “Presenting over half a dozen different possible sources of the problem is wrong.” Unless of course you want to understand why you have a problem. “I’m not interested in every possible way this problem could be triggered.” Of course you aren’t. You’re lazy. You want Ant to figure out your problems for you. “This is a constant, ongoing bug that bedevils everyone who uses Ant with JUnit, as witnessed by the numerous FAQ entries and mailing list posts on the subject.

    No, it most certainly does not bedevil “everyone” who uses Ant with JUnit. It doesn’t bedevil me. Or several thousand others who are happy with the rather competent job Ant does with handling idiotic user errors. Honestly, with users like you I can’t imagine why the good folks writing Ant even bother. I would feel very lucky, if I were you, that one of them was good enough to actually respond to your fumbling, incoherent critisisms by suggesting that you try the latest CVS version. Thanks for the interesting article. I do wonder when this will be deleted…

  5. nickwi Says:

    The first time I saw this error message I was intrigued that someone would go to the trouble of writing such a long message without taking the time to change the code to tell you what the actual problem is. I think shpxnvzer is missing the point. Whilst many users don’t encouter this problem, the one’s that do don’t understand why as the error message doesn’t explain it. As a note, this error is actually caused because the ant task needs both junit.jar and the JDKs tools.jar in the classpath. Those not encountering the message are likely using the JDKs java.exe and the one’s that do using the JREs java.exe.

  6. fletchweb Says:

    A bit harsh

    Your complaint struck a chord in that the message is a bit general and unhelpful, it could certainly give more information. But I find it a bit harsh to write like that about a product you never even paid for. You are obviously benefitting from their work else you wouldn’t be using Ant at all. I think one mistake in an otherwise nice product is probably forgiveable.

  7. fredericiana » Could not create task or type of type: junit. — or the worst error message ever Says:

    […] Unbelievable enough – however, since others did a much better job on ranting about ant’s worst error message ever, I’m going to stop now and provide a solution for that problem instead (since ant developers obviously didn’t feel alike): […]

  8. Andrew Says:

    shpxnvzer… what an asshole… you obviously didn’t read the first post, so caught up in the love you have for ant.

    Ant is a tool, and if it fails for whatever reason, it should tell you exactly what is wrong. It knows that junit is not mispelled so why report that as a possible error? If it cannot find junit.jar, it should tell you that this is the case, and not bother you with other nonsense.

    As a developer, I am not interested in tracking down every possible cause to a problem when the tool should be doing that for me. If a tool can give me the correct information to start with it should (and there is no reason that ant cannot provide this information) – and let me spend my time actually getting on with coding. If the developers of ant want their product to be used (even if it is free) they should realize this, instead of taking insult…

    Yes, ant should figure out the problem for me. Its not being lazy – it is called being productive.

    So you are a better developer who is more familiar with ant… congratulations… you may have the time to play with every setting until you find what works, but some of us actually have work to do, and deadlines to meet…

  9. DD Says:

    Very good comments, I really frustrated with ANT, this message it doesn’t provide useful information on how to fix the problem, I googled several web site, and tried to follow their instruction (copy junit.jar, rebuild, even reinstall the system to remove any lefe over), but none of them work, 🙁 .

  10. Brent Kynaston Says:

    I resolved the issue by placing junit-addons.jar in my ant/lib directory. Have fun!

  11. mahesh Says:

    Ant could not find the task or a class this task relies upon.

    This is common and has a number of causes; the usual
    solutions are to read the manual pages then download and
    install needed JAR files, or fix the build file:
    – You have misspelt ‘extendclasspath’.
    Fix: check your spelling.
    – The task needs an external JAR file to execute
    and this is not found at the right place in the classpath.
    Fix: check the documentation for dependencies.
    Fix: declare the task.
    – The task is an Ant optional task and the JAR file and/or libraries
    implementing the functionality were not found at the time you
    yourself built your installation of Ant from the Ant sources.
    Fix: Look in the ANT_HOME/lib for the ‘ant-‘ JAR corresponding to the
    task and make sure it contains more than merely a META-INF/MANIFEST.MF.
    If all it contains is the manifest, then rebuild Ant with the needed
    libraries present in ${ant.home}/lib/optional/ , or alternatively,
    download a pre-built release version from apache.org
    – The build file was written for a later version of Ant
    Fix: upgrade to at least the latest release version of Ant
    – The task is not an Ant core or optional task
    and needs to be declared using .
    – You are attempting to use a task defined using
    or but have spelt wrong or not
    defined it at the point of use

    Remember that for JAR files to be visible to Ant tasks implemented
    in ANT_HOME/lib, the files must be in the same directory or on the
    classpath

    Total time: 484 milliseconds

  12. ian Says:

    Check out the following link for a definitive solution when working with Eclipse.
    http://www.ryanlowe.ca/blog/archives/001038_junit_ant_task_doesnt_work_in_eclipse.php

  13. Bill Says:

    So, am I the only one who noticed the spelling of “misspelt”. Looks like the ANT developers need to check THEIR spelling. 😉

  14. anon Says:

    LOL lots like you are missing the point of open source here!

    You say you have deadlines to meet which infers that you are using their tool in a commercial environment and getting paid for your work. How much did you pay for Ant?

    Sorry but you get what you pay for in this world and like the previous poster said you have the source code available and you can make the changes.

    Open Source is not built around multi national companies with cash to throw at these projects often its done by people in their spare time.

    By all means write your comments and put your wish list to Ant but quit your whining and look for a commercial alternative if it doesn’t work the way you want it to.

  15. Steve L Says:

    @Bill. “misspelt” is in fact the correct way of spelling the past tense verb “to mispell” in English. “misspelled” is a regional variation. Both are valid. Whatever you can fault us in the Ant team for, it is not for getting misspelt misspelt.

    ps: try the error message in Ant 1.7 -there’s far better diagnostics there.

  16. Andy Says:

    shpxnvzer: i bet your own version of javac also says nothing about which syntax was written incorrectly and which line number huh? retard!

  17. Baron Von Jiblet Says:

    There is one simple solution to this problem: stop using Ant! I have tried multiple versions of it over the years and it continues to break my builds with a different bug in each version. It’s broken by design. As a matter of fact, it can’t even run javac properly: it wants to build every Java source file in the source directory, whereas for a minimal build (e.g. an Applet) you really want to let javac work out the minimal set of sources to build. The solution is to exec out to the command line javac program.

    Ditch ant and use GNU make. Seriously. If you’re stuck on Windows, install Cygwin too. It will save you time.

  18. Alex Says:

    “I find it a bit harsh to write like that about a product you never even paid for.”

    “look for a commercial alternative if it doesn’t work the way you want it to.”

    The sad fact is that there is no commercial alternative because open-source kills commercial opportunity. Instead, we’re *forced* (yes, FORCED) to use ineptly documented and unsupported crap like ant and maven. There’s no way any company I’ve worked for in the past 10 years would pay for a product when there’s some half baked P.O.S. available that is one of the latest buzz-word technologies.

  19. Alex Says:

    Oh, and yes, I’m another developer that just hit this problem and googled that cryptic error message… which is why I find myself here.

    My take on this is that developers need to be aware of their user’s needs. Ant does not have a GUI. The documentation and the console output *is* the user interface. If that is inadequate, then the product is useless.

    It seems to me that ant should know perfectly well the task is defined. I have ant-junit.jar in my ANT_HOME/lib which I believe defines the task. The problem is that ant cannot find the junit libraries that this task depends upon (namely junit.jar). If that means it can’t recognize the task definition, then there is a design flaw in the mechanism. I don’t know much about task definition in ant because welll… I really really really don’t want to know about it. I have more inportant things to worry about like my own software!

    I would suggest the ability to define and use a task is a core user-feature of ant, and ant should therefore support the common use-scenarios that surroud that feature. I.e. missing libraries, misconfigured build.xml files etc etc etc. That’s what ant is supposed to do. The core of ant doesn’t actually do much else does it?

  20. Dave Says:

    Bad to compare open source to commercial guys. You want to take a look at Oracle PL/SQL errors and tell me that ant is poor

  21. Heather Says:

    From what Dave had said, the PL/SQL errors are bad compared to what other open source softwares have done.