When I run the following SOQL query:

SELECT Id, ContactId, Contact.LastName FROM Opportunity

I get the following error on the Contact.LastName field:

System.QueryException: Didn't understand relationship 'Contact' in field path.

Even though ContactId is a Lookup field, the relationship is not recognized. Why?


Opportunity.ContactId represents the Contact record that was created when a lead was converted and an Opportunity was created as a result.

You can dynamically check if a lookup field's relationship is valid with following check:

Opportunity.AccountId.getDescribe().getReferenceTo();  // (Account) - Is a lookup field
Opportunity.AccountId.getDescribe().getRelationshipName();  // Account - As expected

Opportunity.ContactId.getDescribe().getReferenceTo();  // (Contact) - Is a lookup field
Opportunity.ContactId.getDescribe().getRelationshipName();  // null - strange...
  • 2
    How did you manage to retrieve ContactId on Opportunity? Mine code for system.debug(Opportunity.ContactId.getDescribe().getReferenceTo()); throws compilation error, as well as invalid SOQL query for select id, ContactId from Opportunity. Anyway, itis clearly understandable, because Opportunity and Contacts have many-to-many relationship realized through OpportunityContactRole. Jul 3, 2019 at 12:11
  • I'm not sure, but I think newer orgs have Opportunity.ContactId as a background field to keep track of that converted Lead's Contact record. I don't think you can set that field manually Jul 3, 2019 at 12:12

1 Answer 1


Although the type of ContactId on Opportunity is Reference, it seems to be special unlike a traditional lookup field.

Quoting relevant information from the Object reference of Opportunity:

ID of the contact associated with this opportunity, set as the primary contact. Read-only field that is derived from the opportunity contact role, which is created at the same time the opportunity is created. This field can only be populated when it’s created, and can’t be updated. To update the value in this field, change the IsPrimary flag on the OpportunityContactRole associated with this opportunity. Available in API version 46.0 and later.

Also note that this field was added in Summer'19 v46.0:

Set the primary contact at the same time the opportunity is created

Use the ContactID field, set as the primary contact, on the existing Opportunity object.

  • 1
    Great find with the Summer '19 v46.0 release. Looks like it can only be set on insert Jul 3, 2019 at 13:02
  • 1
    @Brain I was curious, so some check on workbench to see more information of the fields, then found it was note available for v45.0 but query worked from developer console, doing some more search luckily found that release notes. Cheers!
    – Raul
    Jul 3, 2019 at 14:01

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .