Recently a few teachers/students have been unable to login to Moodle. With debugging on, typical error output is this:
Debug info: Duplicate entry '971886-5-8833' for key 'mdl_roleassi_conroluse_uix'
INSERT INTO mdl_role_assignments (roleid,contextid,userid,component,itemid,timemodified,modifierid,sortorder) VALUES(?,?,?,?,?,?,?,?)
[array (
0 => '5',
1 => 971886,
2 => '8833',
3 => 'enrol_database',
4 => '21240',
5 => 1614641283,
6 => '10067',
7 => 0,
)]
Error code: dmlwriteexception
Stack trace:
- line 489 of /lib/dml/moodle_database.php: dml_write_exception thrown
- line 1329 of /lib/dml/mysqli_native_moodle_database.php: call to moodle_database->query_end()
- line 1375 of /lib/dml/mysqli_native_moodle_database.php: call to mysqli_native_moodle_database->insert_record_raw()
- line 1529 of /lib/accesslib.php: call to mysqli_native_moodle_database->insert_record()
- line 237 of /enrol/database/lib.php: call to role_assign()
- line 245 of /lib/enrollib.php: call to enrol_database_plugin->sync_user_enrolments()
- line 868 of /lib/classes/session/manager.php: call to enrol_check_plugins()
- line 81 of /course/loginas.php: call to core\session\manager::loginas()
During the user's login, the external database has attempted to enrol the user into a Moodle course, by insert a row into mdl_role_assignments. But this error is spitting out because there is already an enrolment in that course (via the manual enrolment method). To find this, I did an SQL query, using the second and third values (contextid and userid)
SELECT * FROM mdl_context WHERE id = '971886'
That returns a row. The contextlevel is '50' (therefore the context is at the course level). Therefore, the instanceid returned, is the course id. I opened the course (in Moodle), checked the participants. The user has a double enrolment:
The top one is an "external database" enrolment. The bottom one is a "manual enrolment".
Looking at the trace, it seems clear that this is caused by the external database attempting to enrol, when a manual enrolment already exists. I believe it used to be the case that the external database would simply skip enrolments when the user already had an enrolment (via manual enrolment), but I don't know why it is doing this now.
Can anyone suggest how to resolve this?
Moodle version: 3.6.2+ (Build 20190208)
Database: mysql (5.7.33-0 ubuntu 0.18.04.1
PHP: 7.2.34.18.18.04.11