trigger OpportunityTrigger on Opportunity (after insert) {
    if (Trigger.isInsert) {
        List<User> lstUser = [Select Id,isActive From User Where isActive = true And (Profile.Name = 'System Administrator' OR Profile.Name = 'Standard User')];
        List<OpportunityShare> sharesToCreate = new List<OpportunityShare>();
        for (Opportunity oOpportunity : Trigger.new) { 
            if(lstUser != null && lstUser.size() > 0){
                for(User oUsers : lstUser){
                    OpportunityShare oOpportunityShare = new OpportunityShare();
                    oOpportunityShare.UserOrGroupId =  oUsers.Id;
                    System.debug('oOpportunityShare.UserOrGroupId :::>'+oOpportunityShare.UserOrGroupId);
                    oOpportunityShare.OpportunityAccessLevel = 'Edit';
                    System.debug('oOpportunityId :::>'+oOpportunity.Id);
                    oOpportunityShare.OpportunityId = oOpportunity.Id;
        if (!sharesToCreate.isEmpty()){
            insert sharesToCreate;
  • Why are you sharing Opportunities to all users via Apex instead of using a Criteria-Based Sharing Rule or simply changing your Org-Wide Defaults?
    – David Reed
    Nov 10 '20 at 1:16
  • @DavidReed I have a requirement to share Opportunities to all users then revoking the access from the selected users in a custom object which is on Detail side of the Opportunity. Nov 10 '20 at 1:32
  • don't create a share for the Opportunity owner; also, by definition, lstUser will never be null or empty
    – cropredy
    Nov 10 '20 at 1:48
  • There are lots of reasons that this can happen, but I would guess that here it's because a user is creating an Opportunity on an Account to which they have only Read record-level access. Might that be the case? Can you edit to provide more reproduction details?
    – David Reed
    Nov 10 '20 at 2:04
  • I'm also really suspicious of that sharing architecture and I don't think it's going to work very well, but that's a topic too big for this format.
    – David Reed
    Nov 10 '20 at 2:04

So, this error occurs when you try an do an explicit share to the record's owner. So, you can rewrite your trigger to be ..

trigger OpportunityTrigger on Opportunity (after insert) {
  Map<Id,User> usersById= new Map<Id,User> (
                    [Select Id, IsActive 
                        From User 
                        Where isActive = true And 
                              Profile.Name IN ('System Administrator','Standard User')]);
  List<OpportunityShare> sharesToCreate = new List<OpportunityShare>();
  for (Opportunity oppo: Trigger.new) { 
    for(Id shareWithUserId: usersById.keySet()){
       if (oppo.Ownerid = UserInfo.getUserId()) {continue;} // don't share to owner
       sharesToCreate.add(new OpportunityShare(
               UserOrGroupId =  shareWithUserId,
               OpportunityAccessLevel = 'Edit',
               OpportunityId = oppo.Id));
  insert sharesToCreate; // no need to test for empty as empty collection doesn't burn DML

Note: There is a possibility that you'll exceed # DML recs per Transaction (10,000). 200 Oppos and 50 eligible users = 10,000. If that is a realistic possibility, then you'll need to delegate work to a chained set of Queueables

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.