If you are experiencing this issue when you try to get the value from your records (post-processing), you may be running into a similar issue as Unable to retieve dynamic sObject field valueUnable to retieve dynamic sObject field value. You can implement the class I describe there and just do:
for (BOG_Membership__c membership : [/*query*/])
String contactName = CrossObject.get(membership, 'Contact__r.Name');
You can also just hardcode the path:
String contactName = membership.Contact__r.Name;
If you are experiencing this issue when you perform your query, you are almost certainly experiencing an issue with Field Level Security
. I was able to reproduce the behavior you describe by creating a custom object MyObject__c
with a Contact
lookup Contact__c
, and unchecking Visible
for all profiles.
To fix the problem, I clicked into the lookup field and hit the Set Field-Level Security button. Make sure Visible
is checked for your profile (and anyone else who should have access). The reason the Apex
does not blow up is, well, it was designed that way. The Apex Developer Guide states that:
Apex code runs in system context. In system context, Apex code has access to all objects and fields— object permissions, field-level security, sharing rules aren’t applied for the current user. This is to ensure that code won’t fail to run because of hidden fields or objects for a user. The only exceptions to this rule are Apex code that is executed with the executeAnonymous call and Chatter in Apex. executeAnonymous always executes using the full permissions of the current user. For more information on executeAnonymous, see Anonymous Blocks.