Dolibarr/dolibarr · error
Error in some triggers USER_LOGIN or in some hooks…
Error message
Error in some triggers USER_LOGIN or in some hooks afterLogin
What it means
During login, Dolibarr fires the USER_LOGIN trigger and the afterLogin hooks inside a transaction. If any trigger or hook returns an error ($error > 0), main.inc.php rolls back the transaction, destroys the session, prints this hardcoded diagnostic via dol_print_error() and exits. It means a third-party module's trigger/hook is failing, not core Dolibarr.
Solutions
- Check the PHP/server error log and Dolibarr logs (dol_syslog output) for the underlying exception from the trigger/hook.
- Disable recently added/updated modules (run.php setconst or remove the module directory in htdocs/custom) and retry login.
- Inspect llx_document_model / the triggers directory of enabled modules: fix the module's addtrigger/USER_LOGIN code so it returns 0 on success and handles its own DB errors.
- If LDAP/SSO integration is the trigger, verify the external server is reachable and credentials valid.
- Test with only core modules enabled (empty htdocs/custom) to isolate the culprit module.
Example fix
// before (custom trigger)
function runTrigger($action, $object, User $user, Translate $langs, Conf $conf) {
doRiskyLdapSync($user); // may throw / return error
}
// after
function runTrigger($action, $object, User $user, Translate $langs, Conf $conf) {
try { doRiskyLdapSync($user); } catch (Exception $e) {
dol_syslog('USER_LOGIN trigger failed: '.$e->getMessage(), LOG_ERR);
return 0; // don't block login
}
return 0;
} Defensive patterns
Strategy: try-catch
Validate before calling
// before deploying a module, smoke-test its USER_LOGIN trigger
foreach (glob(DOL_DOCUMENT_ROOT.'/custom/*/core/triggers/*.class.php') as $f) {
require_once $f; // fatal here means login will break
} Type guard
function triggerReturnsInt(callable $trigger): bool {
// every Dolibarr trigger must return <0, 0 or >0, never null/throw
try { $r = $trigger(); return is_int($r); } catch (Throwable $e) { return false; }
} Try / catch
try {
$result = $client->post('/api/index.php/login', $credentials);
} catch (ServerException $e) {
// check logs for 'Error in some triggers USER_LOGIN'
disableRecentlyAddedModules();
} Prevention
- Test module install/upgrade on staging before production.
- Keep triggers cheap and failure-tolerant: never let external-service outages (LDAP, SSO) block login.
- Return 0 (not null, no exceptions) from runTrigger on non-fatal issues.
- Monitor dol_syslog warnings during login in CI.
- Keep htdocs/custom under version control so a bad module can be reverted instantly.
When it happens
Trigger: Calling login (web form or API /api/index.php/login) when a module implementing USER_LOGIN (e.g. an LDAP, SSO, or custom business module) raises/returns an error, or an afterLogin hook returns < 0.
Common situations: After installing/upgrading a third-party module; a custom trigger with a bug or unmet dependency (e.g. LDAP server unreachable); module disabled mid-way leaving broken trigger registration; PHP fatal in hook code.
Related errors
- ErrorBadValueForCode
- ErrorBadLoginPassword
- ErrorCantLoadUserFromDolibarrDatabase
- ErrorLoginDateValidity
- ErrorDownloadDocumentHooks
AI-assisted analysis of Dolibarr/dolibarr@598aa4bdad (2026-09-14).
Data as JSON: /api/errors/837c4ff6164d45b3.
Report an issue: GitHub.
Appendix: source
Thrown at htdocs/main.inc.php:1165
$result = $user->call_trigger('USER_LOGIN', $user);
if ($result < 0) {
$error++;
}
// End call triggers
// Hooks on successful login
$action = '';
$hookmanager->initHooks(array('login'));
$parameters = array('dol_authmode' => $dol_authmode, 'dol_loginfo' => $loginfo);
$reshook = $hookmanager->executeHooks('afterLogin', $parameters, $user, $action); // Note that $action and $object may have been modified by some hooks
if ($reshook < 0) {
$error++;
}
if ($error) {
$db->rollback();
session_destroy();
dol_print_error($db, 'Error in some triggers USER_LOGIN or in some hooks afterLogin');
exit;
} else {
$db->commit();
}
// Change landing page if defined.
$landingpage = getDolUserString('MAIN_LANDING_PAGE', getDolGlobalString('MAIN_LANDING_PAGE'));
if (!empty($landingpage)) { // Example: /index.php
$newpath = dol_buildpath($landingpage, 1);
if ($_SERVER["PHP_SELF"] != $newpath) { // not already on landing page (avoid infinite loop)
header('Location: '.$newpath);
exit;
}
}
}
// Check if user must change password at next login
if (!empty($user->force_pass_change) && $dol_authmode == 'dolibarr') {View on GitHub (pinned to 598aa4bdad)