1

I have a flow that is supposed to update multiple Account records and then triggers a process builder to update their related Opportunities. This happens at the start of the new fiscal year to set up the new pricing (which changes annually). I'm getting an error that says "Apex CPU time limit exceeded." I can't find any existing posts related to this error being caused by a flow.

Steps to Reproduce:

  1. Click a button that simply launches the flow.
  2. The flow first finds a Price Book of a certain Tier (custom picklist that exists on Price Book and Account) that has a Start Date of TODAY.
  3. Next, the flow finds all Accounts with the same Tier and updates a Price Book lookup field to match the Price Book that was just found.
  4. These steps are repeated for all 7 tiers. I couldn't process them all at once because I was getting SOQL errors, so I broke it down by Tier.
  5. The edit to the Account's Price Book field triggers a Process Builder, which find the Won Opportunities related to each Account and updates the Price Book field on the Opp, too.

Error: If I have the Process Builder from step 5 turned off, steps 1-4 work just fine. However, if the Process Builder is activated, I'm getting the following error:

The flow tried to update these records: null. This error occurred: CANNOT_INSERT_UPDATE_ACTIVATE_ENTITY: npsp.TDTM_Opportunity: System.LimitException: Apex CPU time limit exceeded.

Also, if I run the flow via the Debug button in the flow builder, it all works, even if the Process Builder is activated.

Flow - Find Tier B Price Book

enter image description here

Flow - Update Tier B Accounts

enter image description here

Process Builder - Update Related Opps

enter image description here

6
  • 1
    This might be soluble in a Flow, but the solution is much cleaner and more scalable by using Batch Apex. Is that an option?
    – David Reed
    Jun 12, 2019 at 20:28
  • If this is a one time thing and you don't have apex skills, you could break it down further by considering only Accounts created in current year, then rerun for accounts created in prior year, etc. (or similar date filtering approach, perhaps on Oppos)
    – cropredy
    Jun 12, 2019 at 20:54
  • @DavidReed I agree that Batch Apex would be better, but my client has refused to use any code. I tried adding the "update opp" step to my original flow, but I still got the same error. Do you know how I could add this to a flow and make it work?
    – Rochelle C
    Jun 13, 2019 at 14:19
  • @cropredy I tried adding the "update opp" task to my original flow and just updated one Tier at a time, hoping that would break things into small enough chunks, but I got the same error.
    – Rochelle C
    Jun 13, 2019 at 14:19
  • 2
    Rochelle. Fundamentally, the flow is doing too much work per transaction and you need to reduce this. The CPU limit is fixed. You could always resort to Data Loader. Or look at the data and see if some Account(s) have a skewed amount of Oppos to update as that could be the issue (an outlier). The debug log can assist.
    – cropredy
    Jun 13, 2019 at 14:35

3 Answers 3

9

The CPU time limit is a cumulative limit across the whole transaction. Essentially, what is happening is that your Flow, plus your Process invocations, plus the NPSP triggers that are run consequent upon the updates you are making, are taking too long to execute in a single transaction (10 seconds of CPU time).

Because the CPU time limit is a cumulative limit, it can be really tricky to put your finger on the cause without careful profiling using the Developer Console. What you see in any logs you might look at following the error is often just the proverbial straw that killed the camel, not the root cause.

Here, I feel fairly confident in saying that this is related to the volume of data that you are trying to update. You've got some moderately large number of Accounts in this Tier, and those Accounts have some number of Opportunities each. Triggers have to run on the updates of all of those records, and that consumes time.

The ultimate fix would probably be to move this functionality to a Batch Apex class, where you have considerably more control over which functionality runs when and can batch your data volume across multiple transactions. Given your client restrictions, I understand the Flow, but I think the result is going to push you to push the client to change their minds.

I previously wrote up an answer about using Wait events to segment a Flow into multiple transactions, and I think that might be something you could apply here.

My proposal - and I will admit that I've only tried this at a PoC level in my own org, and the success or failure will be pretty specific to your Flow - is that your Step 3 is the best place to intervene:

Next, the flow finds all Accounts with the same Tier and updates a Price Book lookup field to match the Price Book that was just found.

Since Accounts are changed after they've passed through this step, I think you could use a Wait element in a loop to query batches of Accounts, update them, Wait to start a new transaction, and then do the next batch.

Get Records in Flow doesn't support a LIMIT clause on its query, which makes this dramatically more difficult. The way I did it was to initialize a Text collection variable with letters of the alphabet, and query Accounts in a loop over that collection using a Starts With condition. Then a Wait skips to a new transaction after each letter.

Here's a rough outline:

flow diagram

Your actual Flow may need to use finer-grained criteria in its loop to break the transactions into small enough pieces. And, as cropredy rightly points out, it's assuming that breaking along Account lines will be enough. It might not be. If one Account has hundreds of Opportunities (or even dozens of Opportunities - in some orgs it doesn't take that much to bounce off the CPU time limiter), chunking by Accounts might not fix the issue anyway.

Honestly, this is a hideous solution. It's clunky as all get out, I don't think the performance will be very good, and it's not all that maintainable like a Flow should be because it's trying to handle data volume that's way too high. Plus, there's a high probability something will change down the road that'll result in the client coming back to complain about new limits problems.

A better solution would be a well-architected, configurable batch process that invokes declarative automation to run smaller pieces of functionality. I would try hard to sell that to the client myself.

2
  • 2
    +1 for "hideous". As you pointed out, this might not work, especially if a single Account had sufficient Oppos to update and the PB for those Oppos blew up CPU time. If it were me with this implacable client, I'd be doing this update via Excel and Data Loader and then get on with my day.
    – cropredy
    Jun 13, 2019 at 16:43
  • Thank you for your thoughts, David. Much appreciated. I agree that this would be much better handled by Batch Apex. I did try a flow like the one you suggested and got some other errors, so I abandoned that path. I think at this point I need to just write instructions for how they can use Data Loader for this task.
    – Rochelle C
    Jun 14, 2019 at 3:12
4

@DavidReed has a pretty clever answer but is not necessarily a guarantee of success without more knowledge of which specific Accounts and their Opportunities incur the CPU time restriction

I'm going to offer two suggestions

Option1 Data Loader (The tried and true)

I get the impression that this task you have is a relatively infrequent event. If so, use reports or Data Loader to export Accounts and their qualifying Opportunities. Manipulate within a spreadsheet tool like Excel and set the value of Opportunity.Pricebook2Id; then use Data Loader to update

Option 2 Mass Action Scheduler

You need to be on Lightning for this impressive tool from Doug Ayers. You can make your Flow run from a source report.

Since you are having CPU time issues, you can create multiple source reports. While I don't know the underlying details of this tool, if the scheduled jobs run as asynchronous processes, then you'll have 60 secs of CPU rather than 10 in a synchronous option.

Disclaimer: I have not used this tool

0

Too Late to the question I faced similar issue which i resolved by restricting the number of fields that i queried for a given object.

1
  • 2
    While this could possibly work, the number of fields being queried shouldn't be that much of a contributing factor. This is probably a sign that there are more serious issues with the flow and/or Apex that the flow is calling.
    – Derek F
    Apr 13 at 12:54

You must log in to answer this question.

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