Can’t create a new XMLDB file

The Moodle XMLDB plugin does some checks of the db/ folder in your plugin to ensure it has read/write access before allowing certain permissions (e.g. create and load). If it doesn’t find this, the text will appear but it won’t be a hyperlink.

Have a look in admin/tool/xmldb/actions/main_view/main_view.class.php

For example for the create button it will have:

 // The create button
                if ($dbdir->path_exists &&
                    !file_exists($key . '/install.xml') &&
                    is_writeable($key)) {                                       

So the db directory needs to exist and be writable by the user running the Moodle instance (e.g. if using apache the user that apache runs as).

Scheduled Tasks: A lock was created but not released

Schedule tasks can use two types of locks:
* Database locks — lock_db table
* File locks — dirroot/lock

The follow error can occur when running a cron through the CLI for example:

!!! Coding error detected, it must be fixed by a programmer: A lock was created but not released at:
[dirroot]/lib/classes/task/manager.php on line 483

 Code should look like:

 $factory = \core\lock\lock_config::get_lock_factory('type');
 $lock = $factory->get_lock(Resource id #585);
 $lock->release();  // Locks must ALWAYS be released like this.

As a starting point, trying disabling the schedule task causing the error and see if you can get the cron to run successfully.

You can try clearing out the locks as well from the database/filestore (whichever is relevant) and running the cron again.

Unknown Error Upgrading Plugin to Version

If you are getting an error like this when attempting to upgrade a plugin:

!!! Unknown error upgrading <pluginname> to version 2017042400, can not continue. !!!
Error code: upgradeerror !!
!! Stack trace: * line 340 of /lib/upgradelib.php: upgrade_exception thrown
* line 549 of /lib/upgradelib.php: call to upgrade_plugin_savepoint()
* line 1630 of /lib/upgradelib.php: call to upgrade_plugins()
* line 171 of /admin/cli/upgrade.php: call to upgrade_noncore()

Then it might be simply due to a missing line in your db/upgrade.php file.

Check that in your function xmldb_<type>_<pluginname>_upgrade($oldversion) function you have a final line that returns a true value.
That is: return true at the end of the function.

XMLDB Editor and Reserved Names

One (of the many) good reasons to use the XMLDB editor in Moodle rather than hacking the db/install.xml file directly is that it warns you if you use a reserved name. For example:

XMLDB Reserved name error

The red Reserved text after [XML] in the screenshot is indicating that the word “column” is reserved and shouldn’t be used. It would be nice if it stopped you from saving such a change (it doesn’t) but at least it indicates a problem.

The Reserved link points to the following location if you ever want to look up the currently used reserved words:


This link also shows you potential existing problems in your XMLDB that may need to be fixed.

Replacing strings in the database through the CLI

There is a tool provided with Moodle to replace strings in your database with another value. This is very useful for things such as site address or domain name changes, and changes from non-SSL (http) to SSL (https).

The tool can be accessed via the following relative URL as a site administrator.

While you can certainly run it from the browser / site, it can timeout and cause problems to do so. Therefore the CLI version is a far better option and available in the moodle code tree under:


php admin/tool/replace/cli/replace.php

Search and replace text throughout the whole database.

--search=STRING       String to search for.
--replace=STRING      String to replace with.
--shorten             Shorten result if necessary.
--non-interactive     Perform the replacement without confirming.
-h, --help            Print out this help.

Note you might need sudo above. So lets say you change your site form to you could run it like so:

php admin/tool/replace/cli/replace.php 
--search= --replace=  --non-interactive

This will scan through tables and give you results in the console as it is going. The non-interactive flag prevents prompting (assuming you are comfortable with the change). If you aren’t you probably shouldn’t use the tool or at least use it on a test site first. The shorten result flag shouldn’t be necessary in most cases.

Resetting a user’s password through the CLI

If you have access to the Moodle server, you can use the admin/cli/reset_password.php script to reset passwords for users with the manual authentication method.

To run this script (from the moodle root code directory), note you may need to sudo as a user with write privileges to the $CFG->dataroot directory.

php admin/cli/reset_password.php

== Password reset ==
Enter username (manual authentication only)
: moodletips
Enter new password
: moodletips

Note the password you specified has to match the password rules configured in Moodle for example the above password moodletips by default would throw:

Passwords must have at least 1 digit(s).
Passwords must have at least 1 upper case letter(s).
Passwords must have at least 1 non-alphanumeric character(s) such as as *, -, or #.

Very handy if you are unable to get into the Moodle site for any reason, or need a quick way to reset a user’s password.

Extended characters in moodle usernames

If you need to use extended characters in usernames, there is a setting under Site Administration > Security > Site Policies called Allow extended characters in usernames extendedusernamechars.

By default moodle usernames must be lowercase and are restricted to alphanumeric characters, the underscore, hypen, period and @ symbol.

You don’t need this if you are using email addresses as usernames (as the @ symbol is allowed) but you might run into a few other edge cases with email addresses:

  • Emails that are mixed case e.g. [email protected] need to be lowercased to [email protected]
  • Emails can have other characters such as an apostrophe (e.g. jack.o’[email protected]) and if you want to preserve such characters you’ll need to turn this setting on. Alternatively you can remove such characters from the username.
  • Emails might have extended language characters in them which required this setting to be turned on as well if you want to match the username to the email addresse exactly.

Also worth noting is that the lib/classes/user.php definition uses PARAM_USERNAME (not PARAM_RAW) anymore in recent versions of moodle. This is used for things like the core user web services. So you will hit invalid parameter exceptions if you specify a username in say mixed case format or with extended characters (and the extendedusernamechars setting is off). This can be confusing it seems like you have specified the wrong parameters but what’s happening is that your parameter does not follow the definition of PARAM_USERNAME. To see the code used to test PARAM_USERNAME have a look in lib/moodlelib.php -> clean_param()

Web service Access control exception

If you are creating or using a web service in Moodle and see the following message:

    "exception": "webservice_access_exception",
    "errorcode": "accessexception",
    "message": "Access control exception"

It can be a bit hard to troubleshoot. Generally there is a 4th item with debugging info, but this will only appear if you have the correct Moodle debugging level set in Site administration > Development > Debugging.

At minimum you’ll need to set Debug messages to NORMAL: Show errors, warnings and notices. That is, it won’t apear if you have it set to NONE or MINIMAL.

Once you do that you should get that 4th parameter:

    "exception": "webservice_access_exception",
    "errorcode": "accessexception",
    "message": "Access control exception",
    "debuginfo": "You are not allowed to use the {$a} protocol (missing capability: webservice/rest:use)"

In this instance, user that is associated with the web service token didn’t have the capability webservice/rest:use in their system role. Adding the capability to the role fixed the issue.

Plugin is defective or outdated, Self test failed

You may see an error like this when upgrading a block:

Default exception handler: Plugin "{block name}" is defective or outdated, can not continue, sorry. Debug: Self test failed.
Error code: detectedbrokenplugin
* line 833 of /lib/upgradelib.php: plugin_defective_exception thrown
* line 425 of /lib/upgradelib.php: call to upgrade_plugins_blocks()
* line 1639 of /lib/upgradelib.php: call to upgrade_plugins()
* line 465 of /admin/index.php: call to upgrade_noncore()

To see what self tests are occuring check the blocks/moodleblock.class.php file at the _self_test() function and check that hte block matches the criteria for having a title, appropriate content, applicable formats, preferred width etc.

$DB->get_record_sql only returning a single row

So you’ve written a query, passed it to $DB->get_records_sql() and, what’s this – only one row? What’s going on, where’s the rest of the query data?

First off, make sure you are using the plural form (get_records_sql() and not get_record_sql()).

If that’s not the issue then read on.

The reason this can happen is that Moodle uses the first column in your query as a unique id and then filters results down to that id field. However, if your first column isn’t unique across your data set, you won’t get every row.

For example, your query may select user enrolments for a course. But if you put your course id as the first column, you’ll only get one row, even if there are 30 enrolments in that course, because all of those enrolments belong to that one course id and that is the unique identifier used.

The fix is simple, find (or if you need to, create) a unique id so that the first column is unique for every row in your query. In the user enrolments example you might use the user ID or the user_enrolments ID.