Skip to Content

Course Access Debugger for LearnDash — Documentation

What this plugin is for

“Why can’t this student see the course?” is the most common LearnDash support question there is, and LearnDash gives you nothing to answer it with. You end up opening the course settings, the user profile, the group, the WooCommerce order and the prerequisite course in five tabs, and reasoning about it by hand.

This plugin does that reasoning for you. Pick a user and a course, and you get the entire access decision as a list of ten checks, each marked Pass, Fail or Not applicable, each with a sentence explaining why, and each with a link to the exact setting that would change it.

It is completely read-only. It never modifies enrolments, orders, groups or settings.

The verdict is LearnDash’s own

The headline at the top of the result — “X CAN access Y” or “X CANNOT access Y” — does not come from this plugin’s own reasoning. It comes from LearnDash’s sfwd_lms_has_access(), the same function the front end uses.

That matters more than it sounds. It means the verdict always agrees with what the learner actually experiences, even in an edge case the ten checks do not model. The checks explain the verdict; they do not replace it.

Requirements

  • WordPress 5.8 or later
  • PHP 7.4 or later
  • LearnDash LMS
  • An administrator account (both screens require manage_options)

WooCommerce is optional. When it is present, the order-state check inspects the order behind a purchased course; when it is not, that check reports as not applicable.

Installation

  1. Install the zip through Plugins → Add New → Upload Plugin, or upload the ld-course-access-debugger folder to /wp-content/plugins/.
  2. Activate it.
  3. Go to LearnDash LMS → Access Debugger.
  4. Pick a user and a course and click Analyze access.

Two screens are added: Access Debugger (one user, one course) and Enrollment Audit (one course, every user).

The access-decision chain

Not enrolled, no group, prerequisite unmet, points short — four reasons, all visible at once.
Not enrolled, no group, prerequisite unmet, points short — four reasons, all visible at once.

Each row is one check. The Status column reads:

StatusMeaning
PassThis rule is satisfied. On checks 1–5 that usually means this is the rule granting access.
FailThis rule is not satisfied. On checks 1–5 it means this particular route does not grant access; on checks 6–10 it means this rule is actively blocking.
Not applicableThe rule does not apply here — the course has no prerequisite, or it is not sold through WooCommerce.

The rule of thumb is printed under the table: one green Pass among checks 1–5 is normally what grants access; checks 6–10 can revoke or delay it even when enrolment exists. A learner can be perfectly enrolled and still locked out by expiry, prerequisites, points or drip.

The ten checks

#CheckWhat it examines
1Capability overrideWhether the user is an administrator, or a group leader with auto-enrol rights. If this passes, access is granted regardless of everything below — which is exactly why testing with your own admin account tells you nothing about what a student sees.
2Direct enrolmentWhether an enrolment record exists for this user and course, and when it was created.
3Group membershipWhether the user belongs to a LearnDash group that grants this course, and which group.
4Course price typeOpen, Free, Buy now, Recurring or Closed — and what each implies. “Free” still requires the user to enrol; “Closed” cannot be joined from the front end at all.
5WooCommerce order stateIf the course is sold through a product, the state of the relevant order. A course that never arrives after payment is almost always an order sitting in on-hold or pending.
6Access expiryWhether course access is time-limited, and if so whether it has run out — with the date.
7PrerequisitesWhether the prerequisite condition is satisfied, in which mode (ALL or ANY), and which specific course is still incomplete. This is the check that saves the most time, because LearnDash’s own message never names the course.
8Course points requirementHow many points the course requires and how many the user has.
9Drip / scheduled releaseWhether a chosen step has been released yet, and on what date it will be. Requires a step to be selected — see below.
10Linear progressionWhether an earlier step is blocking the chosen one, and which step it is, with a link to it.

The Where to fix it column links straight to the relevant settings panel — the course’s Access settings, its prerequisites, its points, the lesson’s release schedule, the groups screen. You are one click from the thing that needs changing.

Checking a single step

With a step chosen, checks 9 and 10 come alive: this lesson has not dripped yet, and progression is blocking it anyway.
With a step chosen, checks 9 and 10 come alive: this lesson has not dripped yet, and progression is blocking it anyway.

Checks 9 and 10 are per-step by nature — drip and linear progression are properties of a lesson, not of a course. Leave the step selector on Entire course and both report as not applicable.

Choose a lesson, topic or quiz from the Step selector and analyse again, and they come alive: whether that step has been released for this user yet, and whether progression requires an earlier step first.

This is the pairing that resolves the second-most-common support ticket — “I’m enrolled but lesson 3 is locked”. The answer is almost always one of these two, and this screen tells you which.

The Enrollment Audit

The roster: 17 users with access, 46 whose access has expired, and the source of every one of them.
The roster: 17 users with access, 46 whose access has expired, and the source of every one of them.

LearnDash LMS → Enrollment Audit answers the opposite question: not “why can’t this one person get in” but “who is actually in this course, and how did they get there?”

Pick a course and you get every user with access, one row each:

ColumnWhat it shows
UserDisplay name and username, linked to the profile.
EmailTheir email address.
Access sourceHow they got in: Direct enrolment, Group membership (with the group named), WooCommerce order (with a link to the order), Open course, or Admin / capability.
GrantedWhen access started.
ExpiresThe expiry date, or Never.
ProgressCourse completion as a percentage bar.

Above the table, a summary counts the total and breaks it down by source — “17 users have access: 16 direct, 1 via admin capability — plus 46 expired users (had access, no longer do)”.

Expired users are worth calling out. They are invisible in LearnDash’s own enrolment lists, because as far as it is concerned they no longer have access. They are also your renewal list.

Filtering, sorting and export

  • Access source filters to one route — including Expired on its own.
  • Search users matches name, login or email.
  • User, Access source, Granted and Expires are sortable. Sorting by expiry is the fastest way to find who lapses next.
  • Export CSV downloads the current result set, filters and all, up to 5,000 rows.

The table paginates at 25 rows, so a course with thousands of learners opens as fast as one with ten.

Why the audit does not disturb anything

Asking LearnDash whether a user has access can, as a side effect, trigger its expiry cleanup — which for a bulk roster would mean the act of looking at your data changing it. The audit therefore resolves verdicts through its own shared resolver rather than calling the per-user access function thousands of times. Reading the roster leaves the roster exactly as it was.

For developers

The rule chain is filterable. Each rule is an id mapping to a label and a callback that returns status (pass, fail or na), a reason, and optionally a fix_url and fix_label:

add_filter( 'ld_cad_rules', function ( $rules ) {
    $rules['my_membership'] = array(
        'label'    => 'Active membership',
        'callback' => 'my_check_membership',
    );

    return $rules;
} );

Because it is an ordinary filter, you can also remove a rule that is noise on your site, or reorder the chain so your own integration is evaluated where it belongs.

Troubleshooting

The verdict says CAN but every check fails

Look at check 1. An administrator or an auto-enrol group leader is granted access by capability, and the other routes genuinely do not apply. Test with a real student account instead.

Checks 9 and 10 always say “Not applicable”

No step is selected. Choose one from the Step selector and analyse again.

The WooCommerce check says the course is not linked to a product

The link is made from the product, not the course: open the product and add the course to its LearnDash Courses field. Until then, orders cannot grant access.

A user is missing from the Enrollment Audit

Check the Access source filter, and remember that expired users are shown separately. If they appear nowhere, they genuinely have no access — run them through the Access Debugger to see why.

The course selector does not list my course

The selectors are capped at 500 courses. On a larger site, use the Access Debugger from a course you can reach and adjust the course ID in the URL.

Frequently asked questions

Does it change enrolments or orders?

No. Both screens are strictly read-only.

Does it work with group leaders and organisational accounts?

Yes. Group membership is check 3, group-leader capability is check 1, and the Enrollment Audit names the group that granted access.

Can I give this to a support person who is not an administrator?

Not as shipped — both screens require manage_options, because they expose every learner’s email address and access history.

Does it work with WooCommerce subscriptions and recurring courses?

The price type check recognises recurring courses, and the order-state check reads the order behind the course. Subscription-specific states are reported through the order they belong to.

Uninstalling

Deactivating removes both screens. The plugin creates no tables and stores no learner data of its own — everything it shows is read live from LearnDash and WooCommerce.