Skip to content

[Bug][4.0.5] Fatal error in update_instructor_capability() when tutor_instructor role is missing #2960

Description

@vmtony

Summary

Tutor LMS 4.0.5 causes a fatal error on every WordPress request when get_role( tutor()->instructor_role ) returns null.

The issue occurs in Tutor::update_instructor_capability(), which calls $role->has_cap() without checking whether the role exists.

Environment

  • Tutor LMS: 4.0.5
  • WordPress: 7.0.4
  • PHP: 8.3.33
  • Existing installation where Tutor LMS had not yet been configured or used

Observed conditions

  • The tutor_instructor role was not present.
  • tutor_removed_edit_other_items_permission was false or absent, so the new capability migration ran.
  • Loading any WordPress endpoint triggered the fatal error, including the frontend, wp-login.php, and wp-admin/.

Error

Uncaught Error: Call to a member function has_cap() on null
in wp-content/plugins/tutor/classes/Tutor.php:1452

Stack trace:
#0 wp-includes/class-wp-hook.php: TUTOR\Tutor->update_instructor_capability()
#1 wp-includes/plugin.php: WP_Hook->do_action()
#2 wp-settings.php: do_action()
#3 wp-config.php
#4 wp-load.php
#5 wp-login.php

The site returned HTTP 500 on all tested WordPress endpoints until Tutor LMS was deactivated through WordPress Recovery Mode.

Root cause

Tutor LMS 4.0.5 added this logic:

$role = get_role( tutor()->instructor_role );

foreach ( $cap_to_be_removed as $cap ) {
    if ( $role->has_cap( $cap ) ) {
        $role->remove_cap( $cap );
    }
}

WordPress documents that get_role() returns WP_Role|null; therefore, the returned value must be checked before calling has_cap():

https://developer.wordpress.org/reference/functions/get_role/

The relevant Tutor LMS commits appear to be:

  • Initial capability change: 95665d2
  • Refactor into update_instructor_capability(): 8473b13

Expected behavior

Tutor LMS should not cause a fatal error when the instructor role is missing.

The capability migration should either:

  1. safely recreate/repair the expected instructor role; or
  2. return without marking the migration complete until a valid WP_Role object exists.

For example:

$role = get_role( tutor()->instructor_role );

if ( ! $role instanceof \WP_Role ) {
    return;
}

The option tutor_removed_edit_other_items_permission should only be updated after the role exists and the intended capabilities have been processed.

Current workaround

Tutor LMS 4.0.5 remains deactivated. No plugin files or course data were deleted.

Please confirm whether the plugin should automatically recreate the missing tutor_instructor role and include a defensive fix in the next release.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions