This forum post may be deleted. I trusted my co-workers code but just went to check the Espo repo and just saw they used the complete wrong method signature for the afterSave
Problem Summary
I'm experiencing a 500 error when saving Leads, and the issue persists even with an almost completely empty AfterSave hook. The error doesn't appear in the EspoCRM logs, making it very difficult to debug.
Background
This minimal hook still causes 500 errors on Lead save:
Even reducing it to the absolute minimum which does nothing but log something:
What I've Tried
Problem Summary
I'm experiencing a 500 error when saving Leads, and the issue persists even with an almost completely empty AfterSave hook. The error doesn't appear in the EspoCRM logs, making it very difficult to debug.
Background
- Initially had ParallelError from Spatie Async library (which I assumed had something to do with the AfterSaveHook making HTTP calls)
- Removed all webhook functionality to isolate the issue
- 500 error persists even with minimal hook code
- No error messages in EspoCRM logs (which might be worse than having errors)
This minimal hook still causes 500 errors on Lead save:
PHP Code:
<?php
namespace Espo\Custom\Hooks\Lead;
use Espo\Core\Hook\Hook\AfterSave;
use Espo\ORM\Entity;
use Espo\ORM\EntityManager;
use Espo\Core\Utils\Log;
use Espo\Core\Utils\Config;
use Espo\Custom\Traits\WebhookTrait;
class AfterSaveHook implements AfterSave
{
//use WebhookTrait;
/** @var string[] */
private const FIELDS_TO_WATCH = [
'cVankoCRM',
'firstName',
'lastName',
'emailAddress',
'phoneNumber',
'cDateOfBirth',
'cTeam',
];
public function __construct(
//private Config $config,
private readonly Log $log,
//private readonly EntityManager $entityManager
) {}
public function afterSave(Entity $lead, array $options, array $data): void
{
try {
//$this->log->info('Lead After Save Hook triggered for Lead ID: ' . $lead->getId());
$isChanged = false;
foreach (self::FIELDS_TO_WATCH as $field) {
/*if ($lead->isAttributeChanged($field)) {
$isChanged = true;
break;
}*/
}
if ($isChanged) {
/*$leadData = [
'crm_id' => $lead->getId(),
'contact_id' => $lead->get('cVankoCRM'),
'first_name' => $lead->get('firstName'),
'last_name' => $lead->get('lastName'),
'email' => $lead->get('emailAddress'),
'phone' => $lead->get('phoneNumber'),
'date_of_birth' => $lead->get('cDateOfBirth'),
];*/
//$this->sendVankoWebhook($leadData);
}
} catch (\Exception $e) {
$this->log->error('Lead After Save Hook error: ' . $e->getMessage());
}
}
private function sendVankoWebhook(array $leadData): void
{
//$endpoint = $this->config->get('vanko.webhooks.lead.process');
if (!$endpoint) {
//$this->log->warning('Vanko webhook endpoint not configured');
return;
}
/*$this->queueWebhook(
endpoint: $endpoint,
payload: $leadData,
serviceName: 'Vanko',
method: 'POST',
timeout: 30
);*/
}
// Required by WebhookTrait
/*protected function getEntityManager(): EntityManager
{
return $this->entityManager;
}
protected function getLog(): Log
{
return $this->log;
}*/
}
PHP Code:
<?php
namespace Espo\Custom\Hooks\Lead;
use Espo\Core\Hook\Hook\AfterSave;
use Espo\ORM\Entity;
class AfterSaveHook implements AfterSave
{
public function afterSave(Entity $lead, array $options, array $data): void
{
$GLOBALS['log']->info("Minimal hook executed");
}
}
- ✅ Removed all HTTP/cURL calls from the hook
- ✅ Commented out all functional logic
- ✅ Removed WebhookTrait usage
- ✅ Cleared cache and rebuilt
- Why would an empty AfterSave hook cause 500 errors?
- How can I debug this when nothing appears in EspoCRM logs?
- Are there specific requirements for AfterSave hook constructors that I'm missing?
- Could there be namespace/autoloading issues?
- EspoCRM version: 9.1.8
- PHP version: 8.4.11
- Lead saves work perfectly when the hook file is removed
Comment