I am getting different results for UserRecordAccess.HasReadAccess, depending on how I query the data:

// Here I use a relationship / foreign key query
List<MyCustomObject__c> records = [
    SELECT Id, Name, UserRecordAccess.HasReadAccess
    FROM MyCustomObject__c
    WHERE Name = :recordName
System.debug(records[0].UserRecordAccess.HasReadAccess); // returns true

// Here I query the UserRecordAccess table directly
        SELECT RecordId, HasReadAccess
        FROM UserRecordAccess
            RecordId = :records[0].Id
            AND UserId = :UserInfo.getUserId()
    .HasReadAccess                                       // returns false

Not sure if it's relevant, but the running user in my real-life example is on a Partner Experience license. They do not appear to have access to the record via global search.

So: why is this happening? Is it a bug or a feature? I don't see anything describing this behavior in the docs.

  • That's odd. They should be consistent, if the running user is the same. Is this in a with sharing/inherited sharing class?
    – sfdcfox
    Mar 8, 2021 at 17:55
  • Sharing settings are unspecified, so they should be defaulting to without sharing. Mar 8, 2021 at 18:08
  • @PeterNoges -- notice that in the 2nd query, I'm using the ID of the record that was returned in the first query. So it's inconceivable that these would be 2 different records. Mar 8, 2021 at 21:29

1 Answer 1


We found that:

  • Querying the UserRecordAccess table merges the contextual user's profile/permissionset based permissions with their sharing access to generate the returned values
  • Querying a record's UserRecordAccess related object does not merge the profile/permissionset permissions and ONLY returns the contextual user's sharing access for that record

We have lived with this for a while and have had to accept it is simply how Salesforce works, whether or not it is actually a bug. It is very annoying.

  • This is interesting. If what you say is true, it strikes me that querying the UserRecordAccess table directly should be more likely to return true than the relationship query approach, not less. Unless I'm misunderstanding something... Mar 8, 2021 at 18:12
  • Please test it for yourself, but we have experienced this with code that is part of our flagship AppExchange package. As to which way the results will vary depends entirely on the combination of permissions and sharing in use.
    – Phil W
    Mar 8, 2021 at 18:20
  • I understand Salesforce permissions to be additive -- each layer of permissions can expose more data, and can't restrict what has already been exposed. Can you describe a scenario where profile/permission set-level permissions would cause a record to be restricted despite record sharing having exposed that record? Mar 8, 2021 at 18:30
  • 1
    Permissions say "not readable" while sharing says "readable".
    – Phil W
    Mar 8, 2021 at 18:42

You must log in to answer this question.

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