These IOErrors are fairly well known, as seen in other SO threads (see below), and can be caused by a user closing their browser mid-upload. For a discussion of why there is no simple solution, see this django-developers thread.
I first tried the middleware option described in an answer to this ioerror SO thread (except in our case I would branch on the request uri). It didn't work: I could capture the response and see that as far as Django was concerned, there wasn't a file included in the post, and it was returning a 200 response with the validation error. And yet, I can still see the IOError in Apache's error log.
Next we found this discussion on a django bug which suggests you should suppress this with a Logging filter. I tried attaching the filter to our custom logger, the root logger and 'django.request' ... I still can't see the IOError to suppress it! I can only see log messages associated with the failed validation of the form.
Any suggestions?
[ Edit: here is my setup ]
In settings.py (mostly copied from Django's conf/global_settings.py
):
DEBUG = False
LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'filters': {
'ioerrsquash': {
'()': 'es.ioerr_filter.IOErrorFilter'
} },
'handlers': {
'mail_admins': {
'level': 'ERROR',
'class': 'django.utils.log.AdminEmailHandler',
'filters': ['ioerrsquash']
}
},
'loggers': {
'django.request': {
'handlers': ['mail_admins'],
'level': 'ERROR',
'propagate': True,
},
'wsgi.errors': { # added this logger after django.request failed
'handlers': ['mail_admins'],
'level': 'ERROR',
'propagate': True,
}
}
}
Content of ioerr_filter.py (obviously just for testing purposes):
import logging
import sys
from django.conf import settings
class IOErrorFilter(logging.Filter):
def filter(self, record):
LOGF = "%s/BU_IOERR.log" % settings.LOG_FILE_DIR
f = open(LOGF, 'a')
f.write('... record\n')
f.write(str(record))
f.write('\n... exc_info\n')
f.write(str(sys.exc_info()))
f.write('\n...\n')
return True