Friday, September 30, 2005

Geeky Friday: Little known vim "feature"

Earlier this week, a co-worker asked for my help diagnosing a problem on one of our sites. Some pages just weren't working in Internet Explorer, but were working fine in Mozilla Firefox.

Odder still, the HTTP status code returned was 199. Normal returns from a web server have status 200, errors are 500, redirects are in the 300 range, 404 is for missing pages. I've never heard of 199. I searched Google and a couple forums for the various software tools that could be involved and found nothing.

So, I went to the source code. Using "find . -mtime -2 -print" to identify all files which had changed in the past two days, I focused on a file I had been testing with the night before.

The extent of my test was adding something along the lines of:

if (some condition) {
print some debug information to the log file
}

I considered this to be safe testing code. It didn't modify any variables, make any database calls, or call other procedures (other than the command to write to the log file). I got the debug information I needed and then edited the file again back to the was it was before. Or so I thought.

It's worth mentioning at this point that I was using vim instead of emacs, my usual text editor.

When I looked at the source code today, I looked at the line immediately following where I had inserted and removed the debug code. It was a line to return (programatically) a web page to the user's browser. One of the arguments to the command is the status code. Instead of the usual "200" I saw "199".

I was bewildered. Clearly this was my fault because the mistake was right where I had been editing this file, but there was no reason for me to have changed this return code. How did this happen?

I fixed the code right away, but I had to know what went wrong. My first guess was that vim had some keystroke shortcut to decrement a number -- it seemed reasonable since the new value was exactly one less than the correct value. So, I googled for "vim decrement" and I was right.

I laughed heartily, especially because the key combination for this is Control-x (C-x) which is used as the beginning for many emacs commands. Most notable, "C-x C-s" is used to save the current file. Clearly what had happened was that my well-trained fingers knew it was time to save the file after I had removed the debugging code and hit "C-x C-s". Unfortunately, the cursor was placed on the number "200" when I did this and vim did what it was programmed to do when fed C-x. My brain kicked in and saved the file in a vim-approved way but I didn't notice the error.

As for the discrepancy between Firefox and Internet Explorer, I wouldn't say that IE did the Wrong Thing, it just did things differently. Firefox looked at the content of the information returned, which looked like valid HTML data, ignored this odd status code and displayed the page. IE, on the other hand, decided that if the status code wasn't 200, it would display an error page. Ok, maybe that is Wrong, it's certainly less elegant and less helpful.

Lessons learned (or rehashed):

There's no such thing as safe testing code on production servers.

Always test changes in more than one browser.

Be extra careful when using an alternate editor or simply stick to one editor