I woke up this morning to a bug in a production environment, it seemed fairly innocuous but being a sensible individual I went off to the sandbox first to replicate it before blundering into production with a fix.

Things got interesting when I couldn’t even get to the page that I needed to in order to test said issue; for some reason I kept getting the error message: Map key null not found in map

I went back to production, ran through the test scenario and sure enough managed to get past this erroneous page and to my original bug. How odd I thought, then I realised: the sandbox had been upgraded over the weekend; I was in Spring ’12’s waters – it had to be something to do with that.

Needless to say after some investigation it does indeed seem to be a “feature” of Spring ’12 so I thought I’d share it for you in all of it’s technicolor glory. And even a simple work around because I’m nice like that.

The code is straight forward enough: an APEX controller that looks like this:

public class TestController{
    private Map<Integer,Account> accs = new Map<Integer,Account>();
    public Map<Integer, Account> getAccounts(){
        return accs;
    }
}


And a VisualForce page that looks like this:

<apex:page controller="TestController">
    <apex:pageBlock >
        <apex:pageBlockTable value="{!accounts}" var="acc">
            <apex:column value="{!accounts[acc].name}" />
        </apex:pageBlockTable>
    </apex:pageBlock>
</apex:page>

The key to the problem is that the Map is initialised but empty. Running the same code in a Winter ’12 environment gets me the following output:

Whilst running it in a Spring ’12 environment gives me this:

Oh dear, for some reason in Spring ’12 the empty Map appears to contain a null key. I ran this through system.debug and the outputs from both environments matched and were as expected. So it would appear that it’s something to do with the VisualForce engine.

There is however a workaround as promised although not terribly exciting and possibly not practical in all scenarios. Having said that it worked for me and I imagine that it could be adapted for pretty much any other situation. I mentioned earlier that the key to the problem was the fact that the Map was initialised but empty. This means that a simple change to our controller to return null when the Map is empty will cure all ills, like so:

public class TestController{
    private Map<Integer,Account> accs = new map<Integer,Account>();
    public Map<Integer, Account> getAccounts(){
        if(accs.size() == 0)
            return null;
        return accs;
    }
}

Hopefully this will save some of you guys a little Monday morning pain; when your code suddenly stops working after an upgrade for no apparent reason.

**** UPDATE ****

This issue seems to go deeper than I first managed to uncover. And whilst the fix above will work for the use case described it won’t work in a whole raft of others. yes, my initial thought that this could be adapted to work around any situation was way off the mark.

I’m having an issue now that appears to be with rehydrating the variables in the controller from the viewstate; although I can’t get deep enough into understand it completely. Looks like I’m waiting on Salesforce support.

**** UPDATE ****

I have had a response on this issue read Empty Maps and VisualForce in Spring ’12: A Conclusion for more details.