Eat Up, Error Messages Are Good for You

Error messages, we all hate them right? They are the little bugs that slap you in the face and say “Stupid, your code doesn’t work! Do it all over again!” The last thing you need hours before an assignment or project is due is to get that lame error that stops you dead in your tracks. You know it is going to happen, so why not just stop, take a deep breath and read them… they are there to help you. Find out how on this episode of the Programming Underground!

Day in and day out on I find the occassional post that reads something like “My stupid project won’t work and all I get is these stupid errors! Help!” or “Help PLEASE!!!” or “NEED HELP ASAP!!” or variations thereof. Often times as helpers we simply look at the error message and read it. I know I know it seems all too simple to us. After all we have been doing this for years and you are just a newbie! That may be true, but you too can read error messages like a pro if you know how to look at them. Error messages are there to protect you after all. They help you, the programmer, understand that something you have written is incorrect before you attempt to run this thing. Some people try to do whatever it takes just to prevent the error from showing and think that their program is then correct rather than trying to understand a message. This is specially the case when the clock is ticking. By understanding the problem and solving one error, often times you will take out dozens of more errors at the same time.

Lets run through some examples from various languages….

LNK2001: unresolved external symbol _main

Now maybe some of you people have run into an error message like this in C++. Unresolved external symbol? Wtf?!?! Often times when you see an error like this it is then followed by only god knows how many errors. However, usually resolving this one error can wipe out a lot of others. But what in the world does it mean! There are a few important pieces that can help you. First of all the code… LNK2001. Often times when you don’t understand an error you can use this code to look up on Google for the given language/compiler you are using to find a dozen other people who are asking about this error too. Usually in the first page you can find a solution as well.

If that doesn’t seem to work well (especially if you are working in some lesser known language like Ada) you can still get hints to what is happening. Through the years error messages have only gotten better and more readable. So we continue to read. Unresolved external symbol…. no clue what that might be, so lets just continue… _main. Interesting, it mentions a function name, variable, struct, class. So lets look in the program for it. Oops! I forgot to include a main function! That is probably the problem! Sure enough, problem solved! Next error please!

A note about errors, half of them usually include a function name, variable, or some kind of struct/class name that you yourself has made. If you see the error say something about “callmyfunctioncat()” good chances are that it is YOUR function and has something to do with how it is called or the code it contains.

Lets look at another one. This time from the world of Java…

';' expected. 'else' without if. statement expected. invalid expression.

Ok, so no error code with this one. But there is plenty of information here as to what might be wrong. The first part says “;” expected. Ok so obviously it expects the semicolon somewhere. What are semicolons used for primarily? To end a statement. So maybe a line is forgetting a semicolon. What else does it say… ‘else’ without if. This could tell us that somewhere it sees an “else statement” but no “if statement” tied to it. Perhaps this has something to do with that semicolon error. If there is no way to end the statement, maybe it thinks that the if statement is part of another statement. Lastly it tells us that this is an invalid expression…. well no duh!

So now we need to go through the code looking for 1) missing semicolon on the end of a line that is 2) relatively close to an if/else statement. After closer inspection we find that the line right before an “if statement” indeed is missing its semicolon and it causes the following if statement to appear as part of the other statement. Leaving our lonely “else statement” out there all alone with no “if statement” to be seen.

Lets dive into the deep parts of PHP….

Parse error: parse error, unexpected T_STRING in <path to file> on line #

I generally find that PHP errors are pretty good at explaining where an error is at, but not always what the problem actually is. To decipher things like this I usually go straight to the line it is complaining about and then look a few lines above it down to the line in question, looking for problems. From this error we can simply read it as a parse error, meaning an error encountered during the read of the code (this is like a compiler error for interpreted languages). The clue here is the “unexpected T_STRING” but what the heck does that mean? Well the key word in that is STRING. Obviously the error has something to do with a string and it is obviously unexpected meaning it just “Shows up” when the parser was expecting something else… like a command of some sort.

The code that generated something like this can be found below…

mysql_connect("localhost", "swaters210", "password") or die(mysql_error());
mysql_select_db("swaters210") or die(mysql_error());
CREATE TABLE data (artist VARCHAR(30), song VARCHAR(30), album VARCHAR(30));
mysql_query("INSERT INTO `data` VALUES ('$artist', '$song', '$album')");

Looking through the lines we see a connect to a database with proper parenthesis, a database selection command, a create table query and a insert query command. So what could be the problem? Well three of the four lines are actually a command while one is simply a string of data. DOH! Look, the create table line is sitting out there not being set to a variable or executed in a command, it is just sitting there doing nothing. PHP is looking for a command and sees this string of text to create a table sitting there. That is our violating string! The correction would be the following…

mysql_connect("localhost", "swaters210", "password") or die(mysql_error());
mysql_select_db("swaters210") or die(mysql_error());
mysql_query("CREATE TABLE data (artist VARCHAR(30), song VARCHAR(30), album VARCHAR(30))";
mysql_query("INSERT INTO `data` VALUES ('$artist', '$song', '$album')");

Now we have it solved! As for our last look at errors we will dive into the world of VB.NET. I like errors in VB because usually the compiler shows you a very readable error but like most .NET languages it also shows you the actual line in question. Plus it gives you some options on what might be causing the problem and how to solve it.

Variable 'myIO' hides a variable in an enclosing block

What does it all mean Martyr!?!?! WHAT DOES IT MEAN! Please please, patience is the key to error messages. Read through them bit by bit and I am sure we can figure it out. The first part reads “Variable ‘myIO'” well obviously we have a variable we named myIO because I don’t think the system would name their variables simple like that. So the error is going to involve that name. It might be in only one area of the code so we could zip there or it might be widely used, so in that case we would have to continue to read. The next part reads “hides a variable in an enclosing block”. Wow, that is a bit cryptic. Well an enclosing block usually means some kind of block of commands, like you would find in an “if statement” or in a loop of some kind. Perhaps what it means by hiding is that the variable is attempting to hide another variable with the same name. Lets look in our code for that variable name and see if in some block it is attempting to either redefine or reinitialize another variable.

Damn that is exactly what is happening! The variable myIO was being redefined in the same function. Why couldn’t it have said something like “myIO is being redefined here on line blah blah blah”. Oh well. here is the offending code.

Public Function mP_IsPathExist(ByVal Path As String) As Boolean

	On Error Resume Next

	Dim myIO As New System.IO.FileInfo(Path)

	If (Not myIO.Exists()) Then 
	   Dim myIO As New System.IO.DirectoryInfo(Path)
	Return myIO.Exists()

End Function

As you can see myIO is being redimmed in the same function block here and so you get the error. There a lot of changes you could make to this function to make it work better and properly (like error trapping in a try catch etc) but that is something for another blog.

Just remember that error messages are your friend and actually protect you from horribly wrong errors before running the program. If you setup a nice testing situation you wouldn’t want a spelling mistake to ruin the test. You would want the compiler to catch it and provide you information as to where your problems might be. It isn’t always the number the errors that is a big deal, solving one error can solve 100 more at the same time. Always start at the top and work your way down one by one and eventually you will get a clean compile.

I leave you with a nice little cartoon I found on errors. Enjoy!

We Goofed

About The Author

Martyr2 is the founder of the Coders Lexicon and author of the new ebooks "The Programmers Idea Book" and "Diagnosing the Problem" . He has been a programmer for over 25 years. He works for a hot application development company in Vancouver Canada which service some of the biggest tech companies in the world. He has won numerous awards for his mentoring in software development and contributes regularly to several communities around the web. He is an expert in numerous languages including .NET, PHP, C/C++, Java and more.