9

I get the following inside a Case Trigger when I try to call a future method: System.AsyncException: Future method cannot be called from a future or batch method

So far this exception ONLY occurs when I'm using Salesforce for Social to convert Tweets to Cases (a.k.a. Salesforce for Twitter and Facebook https://appexchange.salesforce.com/listingDetail?listingId=a0N30000003HpEQEA0).

This Case Trigger is working happily with Cases created by Email to Case, by Radian 6 and by manual creation of a Case.

I don't understand what is different about Salesforce for Social that makes this a future method or batch.

How would I write a unit test to recreate this issue?

How should I fix it?

Here is the Trigger code, which is creating Case Routing Requests for routeable Cases, kind of like a promise to send a Case somewhere. The very last line is where the future method is called ( MC_RoutingRequestManager.ProcessRoutingRequests() ):

trigger MC_CaseTrigger on Case (after insert, after update) { 
    Case[] cases = Trigger.new;
    List<CaseRoutingRequest__c> caseRoutingRequestsToInsert = new List<CaseRoutingRequest__c>();

    for(Case c : cases){
        if(c.Routable__c != true)
        {
            continue;
        }

        Case oldCase;

        if (Trigger.isUpdate)
        {
            oldCase = Trigger.oldMap.get(c.Id);

            //if no status change has occurred for this trigger and case has been routed before
            if(oldCase.Status == c.Status && oldCase.Routable__C == true)
            {
                continue;
            }
        }

        List<CaseRoutingRequest__c> existingCaseRoutingRequests = [select id from CaseRoutingRequest__c where Case__c = :c.Id];

        if(existingCaseRoutingRequests.isEmpty())
        {
            CaseRoutingRequest__c request = new CaseRoutingRequest__c();
            request.Case__c = c.Id;
            caseRoutingRequestsToInsert.add(request);
        }
    }

    if(!caseRoutingRequestsToInsert.isEmpty())
    {
        insert caseRoutingRequestsToInsert;
        MC_RoutingRequestManager.ProcessRoutingRequests();
    }
}

1 Answer 1

10

Do a check in your trigger for

system.isBatch() || system.isFuture()

and if true then exit trigger

7
  • Interesting. Would this not prevent it from working though? Definitely useful to know those commands. Thanks
    – Tom
    Commented Aug 19, 2014 at 15:56
  • 1
    What causes a Trigger to be a future or batch?
    – Tom
    Commented Aug 19, 2014 at 15:57
  • Either code in the org or salesforce code is executing in the future context. Hard to say. It will stop the code from executing when triggered by a batch or future context but you cannot call a future from future anyways so no harm. If you need the code to execute at all times, you will have to change your method to a sync process
    – Eric
    Commented Aug 19, 2014 at 16:12
  • I've not heard of a sync process. I put debug calls in the trigger so I can confirm that it's a future and not a batch.
    – Tom
    Commented Aug 19, 2014 at 16:20
  • 1
    @Tom - Sync process is synchronous process i.e. not batch, not future, typical class and trigger execution. In other words remove the future annotation if possible.
    – Eric
    Commented Aug 19, 2014 at 16:26

You must log in to answer this question.

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