Hooray for spam? Anyway Mike and I managed to solve the bug in emails to each other, and I'm posting the conclusion here for future reference.
The issue was that the form submit code was essentially this: $(form).submit(function(){ if (validate(this)) { displayLoading(); $(this).ajaxSubmit(options); } }); The displayLoading function replaces the content for a given container with a loading graphic - thus destroying the HTML within it. This was being called on the area containing the form, which works fine for regular form submission where the form object contains all the form data already, but apparently causes issues when trying to handle file uploads. So the moral of the story is, if you have a form that's going to upload a file via "AJAX", make sure you don't destroy it in the DOM until the upload is at least started but probably not until it's complete.