7

My managed package contains a trigger for Cases. When users have no license an Apex batch class called from that trigger fails with

First error: Insufficient user privileges

My initial assumption was that packaged code is not called by unlicences users but then I found this thread where it says:

Triggers run in system mode. All the time. Just because the user isn't licensed doesn't mean the trigger itself won't run.

and mentions UserInfo.isCurrentUserLicensedForPackage() to write logic to prevent such errors.

I now have 2 questions:

  1. Is it failing because a Batch job is NOT running in System mode as triggers?
  2. What is the recommended way (documented where?) to prevent such errors in packaged code using UserInfo.isCurrentUserLicensedForPackage()? Are there libraries or patterns to not have this check in every class or my app?
4

Is it failing because a Batch job is NOT running in System mode as triggers?

No, system mode has no effect on if the batch will run. What will be affected is if the user is allowed to edit records.

What is the recommended way (documented where?) to prevent such errors in packaged code using UserInfo.isCurrentUserLicensedForPackage()? Are there libraries or patterns to not have this check in every class or my app?

Honestly, your problem has nothing to do with LMA/licensing/etc. It's exactly what it says on the tin: the user doesn't have permission to operate on one or more records, and you're using non-system-mode (with sharing or inherited sharing).

Standard best practices apply here. Always use partial save (allOrNone=false), or catch DmlException, even if there's no conceivable way you could ever get an error. Avoid leaving the database in an inconsistent state (e.g. always use Database.rollback when using try-catch blocks).

If the batch should only run for licensed users, UserInfo.isCurrentUserLicensedForPackage() is your friend. This is usually uncommon, but this feature exists if you need it. You'll know you need it if your user story starts off with "As a licensed user of this app..." and automatic license enforcement doesn't apply (e.g. it's a Visualforce page or top-level controller class). This is relatively rare.

For debugging this problem, you'll probably want to enable ISV Customer Debugging so you can get the logs and find out what's up.

  • I understand everything you say but not why is uncommon to need the specialized UserInfo method? How should I else prevent any missuse by non-paying users of my app. I also don't get why this should not be relevant for every user story of my app which just says "As a user of this app". A user without a licences is no user, right? – Robert Sösemann Jan 27 at 15:14
  • 1
    @RobertSösemann It's more complicated than "an unlicensed user is not a user". The check is rare to use because triggers are "system logic" and should almost always execute, and other components (e.g. Visualforce) enforce licensing automatically. As far as preventing misuse, that mostly revolves around setting your classes/components/etc as "public" instead of "global." I don't know about your app's design, but it sounds like you shouldn't have used a trigger? This topic likely requires a more concrete example to work through the proper solution. – sfdcfox Jan 27 at 15:34
  • I don’t get why only UI should enforce who uses an app. The app reacts to newly created service cases, but only when the case is created from a user that can use our app. – Robert Sösemann Jan 27 at 15:51
  • @RobertSösemann It may matter because of web-to-case, email-to-case, customer portal users, etc. Again, it may not apply to your case, but you should at least consider what a trigger means. – sfdcfox Jan 27 at 16:28
  • Would using a Platform Event to trigger subsequent changes be a good design to make processing identical for users and non users ? – altius_rup Jan 27 at 21:53

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.