7

I tried below code in my developer Org and observed something strange. I was expecting it to throw a compile time error or at least a Runtime error. But it behaved something else.

public class TestBug {

    public TestBug () {

        // Below commented line behaves as expected
        // Map<String,Account> mapAccount = new Map<String,Account> ([SELECT Id, Name FROM Account LIMIT 100]);

        // This line should give Compile/Runtime time error.
        Map<String,Account> mapAccount = new Map<String,Account> ([SELECT Id, Name FROM Account].Name);
    }
}

Expected Behavior: Compile time error or Runtime error

Output:

Bug

Can anyone explain why this is happening?. Is this a normal behavior or a bug in Apex Compiler?

  • Please do not post multiple questions in one post. If you found another gack, post it separately. – Adrian Larson May 25 '17 at 14:03
11

It looks like you've caused a gack.

What you are looking at is what we call a GACK. A gack is our blue screen of death, our frowny Mac icon, our “the number you have reached is no longer in service”, our “Jedediah has died of dysentery”. A gack is what happens when an error got thrown within our application and we didn’t catch it and handle it.

What this means is that it’s not your fault. It’s ours. That’s why we apologize in that message. Sorry!

This friendly message is the above-water portion of a huge iceberg of functionality. The numbers you see are part of an elaborate system for efficiently bringing these events to the attention of R&D. This post will help you understand that system, and how you can help us in getting you running safely. (Hint: steer away from icebergs.)

Despite what the above says, you can very well cause a gack- this is a great example. They're harder to debug than the average error, and can be caused by just about anything that forces an operation that should never happen.

  • 2
    I don't think single instance vs. list is actually the issue here. If you take the first line from my rewritten code it will compile and run just fine (as long as you add a LIMIT clause. – Adrian Larson Apr 12 '17 at 14:12
  • Looks like when I was trying to figure it out I focused on the soql and less on the map, I've edited my explanation out for the moment. – battery.cord Apr 12 '17 at 14:19
  • @battery.cord I think this should be fixed by Salesforce because I spent almost 2-3 hours finding the root cause as I was working with a class of thousands of lines of code. There was no error message and directly that white screen appeared. Consider a case were a newbie is trying something like this, He/she will never know the root cause of this. Of course community is there but still. – Rohit Mourya Apr 12 '17 at 14:29
  • 1
    @RohitMourya You should always take a reductive approach and try to find a Minimum Viable Reproduction. Even if you are just trying to open a case, MVR is super helpful for support. And often in generating one, you will actually find the root cause. – Adrian Larson Apr 12 '17 at 14:32
  • @AdrianLarson Yes and your answer is also very helpful. Later I came to know that I was doing it wrong, but it took me while to figure it out. – Rohit Mourya Apr 12 '17 at 14:39
6

This is a bug in your code. Class structure is irrelevant. The constructor can essentially be rewritten:

String value = [SELECT Id, Name FROM Account].Name;
Map<String,Account> mapAccount = new Map<String,Account> (value);

Or basically it's the same as:

Map<String,Account> mapAccount = new Map<String,Account> ('Some Account Name');

Of course this code will not compile. Even if it did, the code you wrote would almost certainly fail at run time (unless your instance has exactly one Account record in it). Perhaps the compiler should be able to decipher the problem, but in this case the code is just causing a glitch somewhere.

4

After a bit of testing, it seems that almost any non-list type passed to the Map<ID, sObject> will throw a GACK, while List types are correctly type-checked and issue a compiler error if the type does not match the sObject value type. This includes set, but not map, probably because they will use the copy constructor instead. This only applies if the key of the map is either an ID or String, and the value is an sObject type - any other combination of key and value will issue a compiler warning if an incompatible type is passed, probably because they default to the copy constructor instead of the list constructor.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for?Browse other questions tagged or ask your own question.