I had today the problem, that the loader doesn't hide after a a ajax response is loaded:

My problem is the following error:

"TypeError: Cannot read property 'down' of null
    at Object.bindFieldsChange (http://demo.dev/js/mage/adminhtml/grid.js:280:63)
    at Object.initGrid (http://demo.dev/js/mage/adminhtml/grid.js:80:14)
    at Object.initGridAjax (http://demo.dev/js/mage/adminhtml/grid.js:93:14)
    at http://demo.dev/js/prototype/prototype.js:391:23
    at klass.respondToReadyState (http://demo.dev/js/mage/adminhtml/loader.js:95:68)
    at klass.onStateChange (http://demo.dev/js/prototype/prototype.js:1545:12)
    at XMLHttpRequest.<anonymous> (http://demo.dev/js/prototype/prototype.js:391:23)"

We can't see the error, because magento is catching it and doesn't show it to us.

For debugging purposes we can change the js/mage/adminhtml/grid.js to add this:

    // line 174
    onException: function (response, exception) {

so it looks afterwards like this:

reload : function(url){
    if (!this.reloadParams) {
        this.reloadParams = {form_key: FORM_KEY};
    else {
        this.reloadParams.form_key = FORM_KEY;
    url = url || this.url;
        new Ajax.Request(url + (url.match(new RegExp('\\?')) ? '&ajax=true' : '?ajax=true' ), {
            loaderArea: this.containerId,
            parameters: this.reloadParams || {},
            evalScripts: true,
            onException: function (a,b,c,d,e) {


In my case the problem is a missing ID on the grid

class My_Module_Block_Adminhtml_Tab_Grid
    extends Mage_Adminhtml_Block_Widget_Grid
    implements Mage_Adminhtml_Block_Widget_Tab_Interface
    public function __construct()
        $this->setId('transactionMailFilesGrid'); // <-- this was missing