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
    Aug 19, 2014 at 15:56
  • 1
    What causes a Trigger to be a future or batch?
    – Tom
    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
    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
    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
    Aug 19, 2014 at 16:26

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.