Find your content:

Search form

You are here

Batch Apex in AppExchange package and orgs with related triggers that call @Future methods


Here's the problem: when an org has a trigger that calls an @Future method, any batch Apex that fires that trigger will fail, since you cannot call an @Future method from an @Future method OR from batch Apex. If you do, the following error results:

Type: System.DmlException Message: Update failed. First exception on row 0 with id 00Q3000000y3sIZEAY; first error: CANNOT_INSERT_UPDATE_ACTIVATE_ENTITY, methodNameHere: execution of AfterUpdate caused by: System.AsyncException: Future method cannot be called from a future or batch method

So, if you have a managed package on the AppExchange that includes batch Apex that, for example, updates contacts periodically, and this package is installed into an org that has @Future calls made from inside a contact trigger, your batch Apex will fail to execute.

Has anyone worked through this issue or perhaps does anyone have any suggestions around what options might be available for this scenario?

Thanks in advance!

Attribution to: Adam

Possible Suggestion/Solution #1

Since it turns out System.AsyncException is uncatchable (just tested it) there isn't much you can do to either predict when this is going to happen or resolve it outside of editing the conflicting code.

In short: there's not really a solution other than requiring customers to fix their code to not use @future form non-async safe contexts. And yes, I realize how well that response goes over, I've had to give it more than once.

Attribution to: ca_peterson

Possible Suggestion/Solution #2

You can use the System.isBatch() and System.isFuture() methods to determine if your code is currently executing in an asynchronous context and then function differently rather than trying to catch an async exception.

Any code that initiates async calls (customer org or managed package) should be performing these checks so that code doesn't break down the line when new code is added that also executes async calls.

See the documentation for this here:

Attribution to: E.J. Wilburn

Possible Suggestion/Solution #3

There isn't a way around this, but with the new Queueable interface, you have a solution that you can ask people to implement in their orgs if they are getting this when they use your package.

The Queueable inteface is able to be called safely from a Batch and is in many ways superior to @future calls.

  • It's async, like @future
  • It's deterministic - i.e. it's a fifo structure, so you rely on order of execution
  • You can pass parameters of any type to it.
  • You can chain jobs!

Attribution to: Caspar Harmer
This content is remixed from stackoverflow or stackexchange. Please visit

My Block Status

My Block Content