Error: Future method cannot be called












1















Getting the error below while introducing a new app. The new app is attempting to update all accounts and this is happening. Most likely because it is maxing out the callout limit. I can deactivate it temporarily, but I would prefer to make the the code more stable in order to avoid prevent this from happening again. Any help?




UNIQUE ERRORS UPDATING THE ACCOUNT RECORDS:



AccountChangeToCerbWebhook: execution of AfterUpdate caused by:
System.AsyncException: Future method cannot be called from a future or
batch method: CerbWebhookRequest.Post(String, String) () Please
Specify the Campaign for this Trade Show. Required fields are missing:
[Parent_Company__c]




We have a trigger:



    trigger AccountChangeToCerbWebhook on Account (After insert) {
String webhook_url = 'https://HIDDEN CONTENT';

for(Account a : Trigger.new) {
Map<String, Object> fields = a.getPopulatedFieldsAsMap();

string body = '_=';

for(String fieldKey : fields.keySet()) {
Object fieldValue = fields.get(fieldKey);
String paramValue = '';

if(fieldValue instanceof Datetime) {
paramValue = String.valueOf(((DateTime)fieldValue).getTime()/1000);
} else if(
fieldValue instanceof Boolean
|| fieldValue instanceof Date
|| fieldValue instanceof Decimal
|| fieldValue instanceof Double
|| fieldValue instanceof ID
|| fieldValue instanceof Integer
|| fieldValue instanceof Long
|| fieldValue instanceof String
|| fieldValue instanceof Time
) {
paramValue = String.valueOf(fieldValue);
}

body += '&' + fieldKey + '=' + EncodingUtil.urlEncode(paramValue, 'UTF-8');
}
//if(!Test.isRunningTest()){
CerbWebhookRequest.Post(webhook_url, body);
//}

}
}


Here is the class:



    public with sharing class CerbWebhookRequest {
@future (callout=true)
static public void Post(String url, String body) {
HttpRequest req = new HttpRequest();
HttpResponse res = new HttpResponse();
Http http = new Http();

req.setEndpoint(url);
req.setMethod('POST');
req.setBody(body);

try {
if(!Test.isRunningTest()){
res = http.send(req);
}

} catch(System.CalloutException e) {
System.debug('Callout error: '+ e);
System.debug(res.toString());
}
}
}









share|improve this question




















  • 1





    Are you sure this is your exact code? The error says after update, whereas your trigger is written after insert. Does this trigger happen to be called from a batch or another future method?

    – Jayant Das
    2 hours ago
















1















Getting the error below while introducing a new app. The new app is attempting to update all accounts and this is happening. Most likely because it is maxing out the callout limit. I can deactivate it temporarily, but I would prefer to make the the code more stable in order to avoid prevent this from happening again. Any help?




UNIQUE ERRORS UPDATING THE ACCOUNT RECORDS:



AccountChangeToCerbWebhook: execution of AfterUpdate caused by:
System.AsyncException: Future method cannot be called from a future or
batch method: CerbWebhookRequest.Post(String, String) () Please
Specify the Campaign for this Trade Show. Required fields are missing:
[Parent_Company__c]




We have a trigger:



    trigger AccountChangeToCerbWebhook on Account (After insert) {
String webhook_url = 'https://HIDDEN CONTENT';

for(Account a : Trigger.new) {
Map<String, Object> fields = a.getPopulatedFieldsAsMap();

string body = '_=';

for(String fieldKey : fields.keySet()) {
Object fieldValue = fields.get(fieldKey);
String paramValue = '';

if(fieldValue instanceof Datetime) {
paramValue = String.valueOf(((DateTime)fieldValue).getTime()/1000);
} else if(
fieldValue instanceof Boolean
|| fieldValue instanceof Date
|| fieldValue instanceof Decimal
|| fieldValue instanceof Double
|| fieldValue instanceof ID
|| fieldValue instanceof Integer
|| fieldValue instanceof Long
|| fieldValue instanceof String
|| fieldValue instanceof Time
) {
paramValue = String.valueOf(fieldValue);
}

body += '&' + fieldKey + '=' + EncodingUtil.urlEncode(paramValue, 'UTF-8');
}
//if(!Test.isRunningTest()){
CerbWebhookRequest.Post(webhook_url, body);
//}

}
}


Here is the class:



    public with sharing class CerbWebhookRequest {
@future (callout=true)
static public void Post(String url, String body) {
HttpRequest req = new HttpRequest();
HttpResponse res = new HttpResponse();
Http http = new Http();

req.setEndpoint(url);
req.setMethod('POST');
req.setBody(body);

try {
if(!Test.isRunningTest()){
res = http.send(req);
}

} catch(System.CalloutException e) {
System.debug('Callout error: '+ e);
System.debug(res.toString());
}
}
}









share|improve this question




















  • 1





    Are you sure this is your exact code? The error says after update, whereas your trigger is written after insert. Does this trigger happen to be called from a batch or another future method?

    – Jayant Das
    2 hours ago














1












1








1


1






Getting the error below while introducing a new app. The new app is attempting to update all accounts and this is happening. Most likely because it is maxing out the callout limit. I can deactivate it temporarily, but I would prefer to make the the code more stable in order to avoid prevent this from happening again. Any help?




UNIQUE ERRORS UPDATING THE ACCOUNT RECORDS:



AccountChangeToCerbWebhook: execution of AfterUpdate caused by:
System.AsyncException: Future method cannot be called from a future or
batch method: CerbWebhookRequest.Post(String, String) () Please
Specify the Campaign for this Trade Show. Required fields are missing:
[Parent_Company__c]




We have a trigger:



    trigger AccountChangeToCerbWebhook on Account (After insert) {
String webhook_url = 'https://HIDDEN CONTENT';

for(Account a : Trigger.new) {
Map<String, Object> fields = a.getPopulatedFieldsAsMap();

string body = '_=';

for(String fieldKey : fields.keySet()) {
Object fieldValue = fields.get(fieldKey);
String paramValue = '';

if(fieldValue instanceof Datetime) {
paramValue = String.valueOf(((DateTime)fieldValue).getTime()/1000);
} else if(
fieldValue instanceof Boolean
|| fieldValue instanceof Date
|| fieldValue instanceof Decimal
|| fieldValue instanceof Double
|| fieldValue instanceof ID
|| fieldValue instanceof Integer
|| fieldValue instanceof Long
|| fieldValue instanceof String
|| fieldValue instanceof Time
) {
paramValue = String.valueOf(fieldValue);
}

body += '&' + fieldKey + '=' + EncodingUtil.urlEncode(paramValue, 'UTF-8');
}
//if(!Test.isRunningTest()){
CerbWebhookRequest.Post(webhook_url, body);
//}

}
}


Here is the class:



    public with sharing class CerbWebhookRequest {
@future (callout=true)
static public void Post(String url, String body) {
HttpRequest req = new HttpRequest();
HttpResponse res = new HttpResponse();
Http http = new Http();

req.setEndpoint(url);
req.setMethod('POST');
req.setBody(body);

try {
if(!Test.isRunningTest()){
res = http.send(req);
}

} catch(System.CalloutException e) {
System.debug('Callout error: '+ e);
System.debug(res.toString());
}
}
}









share|improve this question
















Getting the error below while introducing a new app. The new app is attempting to update all accounts and this is happening. Most likely because it is maxing out the callout limit. I can deactivate it temporarily, but I would prefer to make the the code more stable in order to avoid prevent this from happening again. Any help?




UNIQUE ERRORS UPDATING THE ACCOUNT RECORDS:



AccountChangeToCerbWebhook: execution of AfterUpdate caused by:
System.AsyncException: Future method cannot be called from a future or
batch method: CerbWebhookRequest.Post(String, String) () Please
Specify the Campaign for this Trade Show. Required fields are missing:
[Parent_Company__c]




We have a trigger:



    trigger AccountChangeToCerbWebhook on Account (After insert) {
String webhook_url = 'https://HIDDEN CONTENT';

for(Account a : Trigger.new) {
Map<String, Object> fields = a.getPopulatedFieldsAsMap();

string body = '_=';

for(String fieldKey : fields.keySet()) {
Object fieldValue = fields.get(fieldKey);
String paramValue = '';

if(fieldValue instanceof Datetime) {
paramValue = String.valueOf(((DateTime)fieldValue).getTime()/1000);
} else if(
fieldValue instanceof Boolean
|| fieldValue instanceof Date
|| fieldValue instanceof Decimal
|| fieldValue instanceof Double
|| fieldValue instanceof ID
|| fieldValue instanceof Integer
|| fieldValue instanceof Long
|| fieldValue instanceof String
|| fieldValue instanceof Time
) {
paramValue = String.valueOf(fieldValue);
}

body += '&' + fieldKey + '=' + EncodingUtil.urlEncode(paramValue, 'UTF-8');
}
//if(!Test.isRunningTest()){
CerbWebhookRequest.Post(webhook_url, body);
//}

}
}


Here is the class:



    public with sharing class CerbWebhookRequest {
@future (callout=true)
static public void Post(String url, String body) {
HttpRequest req = new HttpRequest();
HttpResponse res = new HttpResponse();
Http http = new Http();

req.setEndpoint(url);
req.setMethod('POST');
req.setBody(body);

try {
if(!Test.isRunningTest()){
res = http.send(req);
}

} catch(System.CalloutException e) {
System.debug('Callout error: '+ e);
System.debug(res.toString());
}
}
}






apex trigger batch class






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited 2 hours ago









gNerb

5,940834




5,940834










asked 2 hours ago









HUBBY0716HUBBY0716

142




142








  • 1





    Are you sure this is your exact code? The error says after update, whereas your trigger is written after insert. Does this trigger happen to be called from a batch or another future method?

    – Jayant Das
    2 hours ago














  • 1





    Are you sure this is your exact code? The error says after update, whereas your trigger is written after insert. Does this trigger happen to be called from a batch or another future method?

    – Jayant Das
    2 hours ago








1




1





Are you sure this is your exact code? The error says after update, whereas your trigger is written after insert. Does this trigger happen to be called from a batch or another future method?

– Jayant Das
2 hours ago





Are you sure this is your exact code? The error says after update, whereas your trigger is written after insert. Does this trigger happen to be called from a batch or another future method?

– Jayant Das
2 hours ago










2 Answers
2






active

oldest

votes


















2














If you are using a batch to update all records, then you cannot call a @future method from within that batch. You should add a method which will do the processing synchronously instead. That way, when you are already asynchronous (such as in a batch), you can just run the synchronous code. That would look roughly like the below:



public class MyClass
{
static Boolean shouldProcessAsync()
{
return !system.isFuture() && !system.isBatch() && !system.isQueueable() &&
Limits.getLimitFutureCalls() > Limits.getFutureCalls();
}

public static void doStuff(List<MyObject__c> records)
{
if (records.isEmpty()) return;

if (shouldProcessAsync())
{
doStuffAsync(new Map<Id, SObject>(records).keySet());
}
else
{
// logic
}
}
@future(callout=true)
static void doStuffAsync(Set<Id> recordIds)
{
doStuff([
SELECT Name
FROM MyObject__c
WHERE Id IN :recordIds
]);
}
}





share|improve this answer


























  • I am happy to take a further look in chat.

    – Adrian Larson
    33 mins ago













  • I joined the chat, but didn't see you in there

    – HUBBY0716
    3 mins ago











  • Yeah I left after you didn't join for a while.

    – Adrian Larson
    49 secs ago



















2














Looks like you have two separate errors here, neither of which is related to the callout limit (although you're right to worry about that; more below).




AccountChangeToCerbWebhook: execution of AfterUpdate caused by:
System.AsyncException: Future method cannot be called from a future or
batch method: CerbWebhookRequest.Post(String, String)




Your callout logic needs to be context-aware. If you're in a batch class - it sounds like your package is running a batch class which executes updates on Account - you should make the callout synchronously. Adrian's answer describes a good architecture to adopt for this handling.




Please Specify the Campaign for this Trade Show. Required fields are
missing: [Parent_Company__c]




This is a different error that typically indicates your existing data does not meet invariants required by your validation rules. Since the Accounts are being updated, the validation rules will all be evaluated and will block the update if they add an error. You can fix this in several ways.




  1. Fix the data.

  2. Deactivate the validation rule.

  3. Add an exclusion to the validation rule so that it does not run on a specific User or Profile, ideally by referencing a Custom Permission that you place on the data load or integration user via a Permission Set.



Most likely because it is maxing out the callout limit




It's not, but you're right to worry about that because you're making one callout per Account, and the callout limit is 50 per transaction. So if the batch class is running at a batch size of 200, you have a problem there. If you have control over the batch size, you can turn it down at the cost of increased processing time.



The integration architecture you're using is inherently limited, though. It's never a good idea to fire one future call per transaction record.






share|improve this answer


























  • I just wrote a comment on something similar, My guess for the error since the error says after update but the trigger fires in after insert, is that there is a different trigger calling a future method to create an account which then fires the account trigger causing the first error.

    – gNerb
    2 hours ago













  • Oh, nice catch. I would be willing to bet that the poster has an after update trigger that calls the exact same webhook in the same way, and his "new app" is running a batch process that executes update DML. We'll see.

    – David Reed
    2 hours ago











  • I didn't work on this project so I'm doing some digging here. I don't see an after update, but see what you mean. The new app may have the after update, but the code is hidden.

    – HUBBY0716
    1 hour ago











  • Could you edit your question to include a complete stack trace?

    – David Reed
    1 hour ago











Your Answer








StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "459"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});














draft saved

draft discarded


















StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fsalesforce.stackexchange.com%2fquestions%2f246841%2ferror-future-method-cannot-be-called%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown

























2 Answers
2






active

oldest

votes








2 Answers
2






active

oldest

votes









active

oldest

votes






active

oldest

votes









2














If you are using a batch to update all records, then you cannot call a @future method from within that batch. You should add a method which will do the processing synchronously instead. That way, when you are already asynchronous (such as in a batch), you can just run the synchronous code. That would look roughly like the below:



public class MyClass
{
static Boolean shouldProcessAsync()
{
return !system.isFuture() && !system.isBatch() && !system.isQueueable() &&
Limits.getLimitFutureCalls() > Limits.getFutureCalls();
}

public static void doStuff(List<MyObject__c> records)
{
if (records.isEmpty()) return;

if (shouldProcessAsync())
{
doStuffAsync(new Map<Id, SObject>(records).keySet());
}
else
{
// logic
}
}
@future(callout=true)
static void doStuffAsync(Set<Id> recordIds)
{
doStuff([
SELECT Name
FROM MyObject__c
WHERE Id IN :recordIds
]);
}
}





share|improve this answer


























  • I am happy to take a further look in chat.

    – Adrian Larson
    33 mins ago













  • I joined the chat, but didn't see you in there

    – HUBBY0716
    3 mins ago











  • Yeah I left after you didn't join for a while.

    – Adrian Larson
    49 secs ago
















2














If you are using a batch to update all records, then you cannot call a @future method from within that batch. You should add a method which will do the processing synchronously instead. That way, when you are already asynchronous (such as in a batch), you can just run the synchronous code. That would look roughly like the below:



public class MyClass
{
static Boolean shouldProcessAsync()
{
return !system.isFuture() && !system.isBatch() && !system.isQueueable() &&
Limits.getLimitFutureCalls() > Limits.getFutureCalls();
}

public static void doStuff(List<MyObject__c> records)
{
if (records.isEmpty()) return;

if (shouldProcessAsync())
{
doStuffAsync(new Map<Id, SObject>(records).keySet());
}
else
{
// logic
}
}
@future(callout=true)
static void doStuffAsync(Set<Id> recordIds)
{
doStuff([
SELECT Name
FROM MyObject__c
WHERE Id IN :recordIds
]);
}
}





share|improve this answer


























  • I am happy to take a further look in chat.

    – Adrian Larson
    33 mins ago













  • I joined the chat, but didn't see you in there

    – HUBBY0716
    3 mins ago











  • Yeah I left after you didn't join for a while.

    – Adrian Larson
    49 secs ago














2












2








2







If you are using a batch to update all records, then you cannot call a @future method from within that batch. You should add a method which will do the processing synchronously instead. That way, when you are already asynchronous (such as in a batch), you can just run the synchronous code. That would look roughly like the below:



public class MyClass
{
static Boolean shouldProcessAsync()
{
return !system.isFuture() && !system.isBatch() && !system.isQueueable() &&
Limits.getLimitFutureCalls() > Limits.getFutureCalls();
}

public static void doStuff(List<MyObject__c> records)
{
if (records.isEmpty()) return;

if (shouldProcessAsync())
{
doStuffAsync(new Map<Id, SObject>(records).keySet());
}
else
{
// logic
}
}
@future(callout=true)
static void doStuffAsync(Set<Id> recordIds)
{
doStuff([
SELECT Name
FROM MyObject__c
WHERE Id IN :recordIds
]);
}
}





share|improve this answer















If you are using a batch to update all records, then you cannot call a @future method from within that batch. You should add a method which will do the processing synchronously instead. That way, when you are already asynchronous (such as in a batch), you can just run the synchronous code. That would look roughly like the below:



public class MyClass
{
static Boolean shouldProcessAsync()
{
return !system.isFuture() && !system.isBatch() && !system.isQueueable() &&
Limits.getLimitFutureCalls() > Limits.getFutureCalls();
}

public static void doStuff(List<MyObject__c> records)
{
if (records.isEmpty()) return;

if (shouldProcessAsync())
{
doStuffAsync(new Map<Id, SObject>(records).keySet());
}
else
{
// logic
}
}
@future(callout=true)
static void doStuffAsync(Set<Id> recordIds)
{
doStuff([
SELECT Name
FROM MyObject__c
WHERE Id IN :recordIds
]);
}
}






share|improve this answer














share|improve this answer



share|improve this answer








edited 2 hours ago

























answered 2 hours ago









Adrian LarsonAdrian Larson

106k19113239




106k19113239













  • I am happy to take a further look in chat.

    – Adrian Larson
    33 mins ago













  • I joined the chat, but didn't see you in there

    – HUBBY0716
    3 mins ago











  • Yeah I left after you didn't join for a while.

    – Adrian Larson
    49 secs ago



















  • I am happy to take a further look in chat.

    – Adrian Larson
    33 mins ago













  • I joined the chat, but didn't see you in there

    – HUBBY0716
    3 mins ago











  • Yeah I left after you didn't join for a while.

    – Adrian Larson
    49 secs ago

















I am happy to take a further look in chat.

– Adrian Larson
33 mins ago







I am happy to take a further look in chat.

– Adrian Larson
33 mins ago















I joined the chat, but didn't see you in there

– HUBBY0716
3 mins ago





I joined the chat, but didn't see you in there

– HUBBY0716
3 mins ago













Yeah I left after you didn't join for a while.

– Adrian Larson
49 secs ago





Yeah I left after you didn't join for a while.

– Adrian Larson
49 secs ago













2














Looks like you have two separate errors here, neither of which is related to the callout limit (although you're right to worry about that; more below).




AccountChangeToCerbWebhook: execution of AfterUpdate caused by:
System.AsyncException: Future method cannot be called from a future or
batch method: CerbWebhookRequest.Post(String, String)




Your callout logic needs to be context-aware. If you're in a batch class - it sounds like your package is running a batch class which executes updates on Account - you should make the callout synchronously. Adrian's answer describes a good architecture to adopt for this handling.




Please Specify the Campaign for this Trade Show. Required fields are
missing: [Parent_Company__c]




This is a different error that typically indicates your existing data does not meet invariants required by your validation rules. Since the Accounts are being updated, the validation rules will all be evaluated and will block the update if they add an error. You can fix this in several ways.




  1. Fix the data.

  2. Deactivate the validation rule.

  3. Add an exclusion to the validation rule so that it does not run on a specific User or Profile, ideally by referencing a Custom Permission that you place on the data load or integration user via a Permission Set.



Most likely because it is maxing out the callout limit




It's not, but you're right to worry about that because you're making one callout per Account, and the callout limit is 50 per transaction. So if the batch class is running at a batch size of 200, you have a problem there. If you have control over the batch size, you can turn it down at the cost of increased processing time.



The integration architecture you're using is inherently limited, though. It's never a good idea to fire one future call per transaction record.






share|improve this answer


























  • I just wrote a comment on something similar, My guess for the error since the error says after update but the trigger fires in after insert, is that there is a different trigger calling a future method to create an account which then fires the account trigger causing the first error.

    – gNerb
    2 hours ago













  • Oh, nice catch. I would be willing to bet that the poster has an after update trigger that calls the exact same webhook in the same way, and his "new app" is running a batch process that executes update DML. We'll see.

    – David Reed
    2 hours ago











  • I didn't work on this project so I'm doing some digging here. I don't see an after update, but see what you mean. The new app may have the after update, but the code is hidden.

    – HUBBY0716
    1 hour ago











  • Could you edit your question to include a complete stack trace?

    – David Reed
    1 hour ago
















2














Looks like you have two separate errors here, neither of which is related to the callout limit (although you're right to worry about that; more below).




AccountChangeToCerbWebhook: execution of AfterUpdate caused by:
System.AsyncException: Future method cannot be called from a future or
batch method: CerbWebhookRequest.Post(String, String)




Your callout logic needs to be context-aware. If you're in a batch class - it sounds like your package is running a batch class which executes updates on Account - you should make the callout synchronously. Adrian's answer describes a good architecture to adopt for this handling.




Please Specify the Campaign for this Trade Show. Required fields are
missing: [Parent_Company__c]




This is a different error that typically indicates your existing data does not meet invariants required by your validation rules. Since the Accounts are being updated, the validation rules will all be evaluated and will block the update if they add an error. You can fix this in several ways.




  1. Fix the data.

  2. Deactivate the validation rule.

  3. Add an exclusion to the validation rule so that it does not run on a specific User or Profile, ideally by referencing a Custom Permission that you place on the data load or integration user via a Permission Set.



Most likely because it is maxing out the callout limit




It's not, but you're right to worry about that because you're making one callout per Account, and the callout limit is 50 per transaction. So if the batch class is running at a batch size of 200, you have a problem there. If you have control over the batch size, you can turn it down at the cost of increased processing time.



The integration architecture you're using is inherently limited, though. It's never a good idea to fire one future call per transaction record.






share|improve this answer


























  • I just wrote a comment on something similar, My guess for the error since the error says after update but the trigger fires in after insert, is that there is a different trigger calling a future method to create an account which then fires the account trigger causing the first error.

    – gNerb
    2 hours ago













  • Oh, nice catch. I would be willing to bet that the poster has an after update trigger that calls the exact same webhook in the same way, and his "new app" is running a batch process that executes update DML. We'll see.

    – David Reed
    2 hours ago











  • I didn't work on this project so I'm doing some digging here. I don't see an after update, but see what you mean. The new app may have the after update, but the code is hidden.

    – HUBBY0716
    1 hour ago











  • Could you edit your question to include a complete stack trace?

    – David Reed
    1 hour ago














2












2








2







Looks like you have two separate errors here, neither of which is related to the callout limit (although you're right to worry about that; more below).




AccountChangeToCerbWebhook: execution of AfterUpdate caused by:
System.AsyncException: Future method cannot be called from a future or
batch method: CerbWebhookRequest.Post(String, String)




Your callout logic needs to be context-aware. If you're in a batch class - it sounds like your package is running a batch class which executes updates on Account - you should make the callout synchronously. Adrian's answer describes a good architecture to adopt for this handling.




Please Specify the Campaign for this Trade Show. Required fields are
missing: [Parent_Company__c]




This is a different error that typically indicates your existing data does not meet invariants required by your validation rules. Since the Accounts are being updated, the validation rules will all be evaluated and will block the update if they add an error. You can fix this in several ways.




  1. Fix the data.

  2. Deactivate the validation rule.

  3. Add an exclusion to the validation rule so that it does not run on a specific User or Profile, ideally by referencing a Custom Permission that you place on the data load or integration user via a Permission Set.



Most likely because it is maxing out the callout limit




It's not, but you're right to worry about that because you're making one callout per Account, and the callout limit is 50 per transaction. So if the batch class is running at a batch size of 200, you have a problem there. If you have control over the batch size, you can turn it down at the cost of increased processing time.



The integration architecture you're using is inherently limited, though. It's never a good idea to fire one future call per transaction record.






share|improve this answer















Looks like you have two separate errors here, neither of which is related to the callout limit (although you're right to worry about that; more below).




AccountChangeToCerbWebhook: execution of AfterUpdate caused by:
System.AsyncException: Future method cannot be called from a future or
batch method: CerbWebhookRequest.Post(String, String)




Your callout logic needs to be context-aware. If you're in a batch class - it sounds like your package is running a batch class which executes updates on Account - you should make the callout synchronously. Adrian's answer describes a good architecture to adopt for this handling.




Please Specify the Campaign for this Trade Show. Required fields are
missing: [Parent_Company__c]




This is a different error that typically indicates your existing data does not meet invariants required by your validation rules. Since the Accounts are being updated, the validation rules will all be evaluated and will block the update if they add an error. You can fix this in several ways.




  1. Fix the data.

  2. Deactivate the validation rule.

  3. Add an exclusion to the validation rule so that it does not run on a specific User or Profile, ideally by referencing a Custom Permission that you place on the data load or integration user via a Permission Set.



Most likely because it is maxing out the callout limit




It's not, but you're right to worry about that because you're making one callout per Account, and the callout limit is 50 per transaction. So if the batch class is running at a batch size of 200, you have a problem there. If you have control over the batch size, you can turn it down at the cost of increased processing time.



The integration architecture you're using is inherently limited, though. It's never a good idea to fire one future call per transaction record.







share|improve this answer














share|improve this answer



share|improve this answer








edited 2 hours ago









gNerb

5,940834




5,940834










answered 2 hours ago









David ReedDavid Reed

31.8k71746




31.8k71746













  • I just wrote a comment on something similar, My guess for the error since the error says after update but the trigger fires in after insert, is that there is a different trigger calling a future method to create an account which then fires the account trigger causing the first error.

    – gNerb
    2 hours ago













  • Oh, nice catch. I would be willing to bet that the poster has an after update trigger that calls the exact same webhook in the same way, and his "new app" is running a batch process that executes update DML. We'll see.

    – David Reed
    2 hours ago











  • I didn't work on this project so I'm doing some digging here. I don't see an after update, but see what you mean. The new app may have the after update, but the code is hidden.

    – HUBBY0716
    1 hour ago











  • Could you edit your question to include a complete stack trace?

    – David Reed
    1 hour ago



















  • I just wrote a comment on something similar, My guess for the error since the error says after update but the trigger fires in after insert, is that there is a different trigger calling a future method to create an account which then fires the account trigger causing the first error.

    – gNerb
    2 hours ago













  • Oh, nice catch. I would be willing to bet that the poster has an after update trigger that calls the exact same webhook in the same way, and his "new app" is running a batch process that executes update DML. We'll see.

    – David Reed
    2 hours ago











  • I didn't work on this project so I'm doing some digging here. I don't see an after update, but see what you mean. The new app may have the after update, but the code is hidden.

    – HUBBY0716
    1 hour ago











  • Could you edit your question to include a complete stack trace?

    – David Reed
    1 hour ago

















I just wrote a comment on something similar, My guess for the error since the error says after update but the trigger fires in after insert, is that there is a different trigger calling a future method to create an account which then fires the account trigger causing the first error.

– gNerb
2 hours ago







I just wrote a comment on something similar, My guess for the error since the error says after update but the trigger fires in after insert, is that there is a different trigger calling a future method to create an account which then fires the account trigger causing the first error.

– gNerb
2 hours ago















Oh, nice catch. I would be willing to bet that the poster has an after update trigger that calls the exact same webhook in the same way, and his "new app" is running a batch process that executes update DML. We'll see.

– David Reed
2 hours ago





Oh, nice catch. I would be willing to bet that the poster has an after update trigger that calls the exact same webhook in the same way, and his "new app" is running a batch process that executes update DML. We'll see.

– David Reed
2 hours ago













I didn't work on this project so I'm doing some digging here. I don't see an after update, but see what you mean. The new app may have the after update, but the code is hidden.

– HUBBY0716
1 hour ago





I didn't work on this project so I'm doing some digging here. I don't see an after update, but see what you mean. The new app may have the after update, but the code is hidden.

– HUBBY0716
1 hour ago













Could you edit your question to include a complete stack trace?

– David Reed
1 hour ago





Could you edit your question to include a complete stack trace?

– David Reed
1 hour ago


















draft saved

draft discarded




















































Thanks for contributing an answer to Salesforce Stack Exchange!


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fsalesforce.stackexchange.com%2fquestions%2f246841%2ferror-future-method-cannot-be-called%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

Polycentropodidae

Magento 2 Error message: Invalid state change requested

Paulmy