LifterLMS Emails Not Sending? How to Find and Fix the Cause
Find out why LifterLMS emails are not arriving and fix it: tell sending failures from delivery failures, set up SMTP and a matching sender address…
Read articleDiagnose a LifterLMS lesson that will not mark complete: quiz and assignment requirements, minimum lesson time, cached pages with expired security tokens, JavaScript conflicts and enrollment, with a symptom table and a way to complete the lesson for a stuck student.
A student clicks Mark Complete and nothing happens. Or the button is greyed out, or missing, or the next lesson opens but the last one is still not ticked. When LifterLMS mark complete is not working, the cause is nearly always one of a handful of rules or conflicts, and most of them can be identified in a few minutes.
This guide explains what happens when the button is clicked, then works through each cause by the symptom it produces. It also shows how to complete a lesson for a stuck student while you fix the underlying problem, and includes a small logging snippet for developers.
The button submits a small form back to the lesson page. On the server, LifterLMS then runs three checks in order:
Then, by default, LifterLMS redirects to the next lesson. That redirect happens whether or not step 3 allowed completion. This is why a student can end up on lesson 4 with lesson 3 still incomplete, and why "it moved on but didn't save" is a symptom of a rule blocking completion rather than a database fault.
| What the student sees | Look at first |
|---|---|
| No Mark Complete button, a Take Quiz button instead | A quiz is attached to the lesson |
| No button at all | Not enrolled, lesson not yet available, or a page builder template missing the button |
| Button visible but greyed out | Minimum lesson time still running, or JavaScript not running |
| Click reloads the page and nothing changes | Cached page with an expired security token |
| Next lesson opens, previous lesson not ticked | A completion rule blocked it: quiz, minimum time or an add-on |
| "You are not allowed to complete this lesson." | Enrollment, expired access, drip or prerequisite |
| Lesson ticked, but progress or course completion looks wrong | Caching of progress or a completion requirement elsewhere in the course |
When a lesson has a published quiz, the Mark Complete button is replaced by Take Quiz, and finishing the quiz is what completes the lesson. Two settings decide what counts:
So a student who failed a required quiz cannot complete the lesson by any button. They need another attempt, or you need to review the quiz settings. Our guide to creating quizzes in LifterLMS covers attempts and passing grades, and an unpublished quiz is ignored entirely.
The paid Assignments add-on works the same way: a lesson with an assignment is completed through the assignment, by submitting it or by passing it, depending on how it is set up. If a student says they submitted but the lesson is incomplete, check the assignment's status and grading settings in that add-on.
Since version 10.1, a lesson can require a minimum time before it can be completed, using the Enable Minimum Time setting with hours, minutes and seconds. While the time is running, the Mark Complete and Take Quiz buttons are disabled in the page markup, and a timer shows progress.
How it counts matters when troubleshooting:
Version 10.1.1 fixed a case where clicking at the exact moment the time was reached was rejected, so update if you are on 10.1.0. Our article on LifterLMS lesson time tracking covers the setting in depth, and the official lesson time tracking documentation describes how the timer pauses and resumes.
If the page reloads and nothing changes, suspect caching first. The Mark Complete form contains a nonce that WordPress generates for the logged-in user and that expires after a day or so. A page cache that serves a stored copy of the lesson to a logged-in student hands them someone else's or yesterday's token, and LifterLMS silently discards the submission.
The same problem breaks the lesson timer, which needs a fresh token for its heartbeat. Typical culprits are server-level or CDN "cache everything" rules that ignore WordPress login cookies, and caching plugins configured to cache pages for logged-in users.
The fix is to never serve cached HTML to logged-in users on course, lesson and quiz pages. Our guide to configuring caching for LifterLMS has the exclusion rules for common caching layers.
Several parts of the lesson page depend on JavaScript: the minimum time timer that enables the button, the quiz interface, and some add-on requirements. If scripts fail, buttons stay disabled forever.
"You are not allowed to complete this lesson" means the permission check failed: the student is not enrolled in the course, their access has expired or been cancelled, or the lesson is not yet available because of drip or a prerequisite. Our guide to diagnosing course access problems walks through each of those.
Be careful testing as an administrator. Users who can edit the lesson are always allowed to complete it, so an admin test hides permission problems. Use a real test student account.
If the lesson is complete but the student says their progress bar is wrong, check for page caching first, then for completion requirements elsewhere: a course is only complete when every lesson is.
While you fix the cause, you can unblock a student from the admin:
An admin completion overrides minimum time, which is recorded as an override. It does not override quiz requirements: the action is hidden for a lesson whose quiz the student has not yet satisfied.
For developers, this snippet logs every blocked completion with the lesson, user and trigger, so you can see which rule is saying no. It runs after core's own checks, and the entries appear under LifterLMS > Status > Logs:
<?php
add_filter( 'llms_allow_lesson_completion', 'llmsx_log_blocked_completion', 999, 5 );
function llmsx_log_blocked_completion( $allow, $user_id, $lesson_id, $trigger, $args ) {
if ( ! $allow ) {
llms_log(
sprintf( 'Completion blocked: lesson #%d, user #%d, trigger "%s"', $lesson_id, $user_id, $trigger ),
'lesson-completion'
);
}
return $allow;
}
Usually because the lesson has a quiz, which replaces it with Take Quiz. Otherwise the student is not enrolled, the lesson is not yet available, or your theme or page builder template does not output the button.
The lesson has a minimum time that has not been met, or the JavaScript that enables the button is not running. Check the timer and the browser console.
Only if Retake Lessons is enabled under LifterLMS > Settings > Courses. Administrators can always mark a lesson incomplete from the student's course report.
Administrators bypass permission checks and are rarely served cached pages. Test with a real student account in a private browser window.
Match the symptom in the table, check that one cause, and retest as a real student. If you cannot reproduce the problem, add the logging snippet and wait for the next report; the trigger and lesson ID usually point straight at the rule involved.
If completion rules, caching and add-ons are tangled together on your site, our LifterLMS support team can find the conflict on a staging copy. Send us the lesson URL and what the student sees.
Find out why LifterLMS emails are not arriving and fix it: tell sending failures from delivery failures, set up SMTP and a matching sender address…
Read article
A step-by-step plan for moving from Teachable to LifterLMS: what Teachable lets you export, how to rebuild courses, import and enroll students…
Read article
A practical WCAG checklist for a LifterLMS academy: what the plugin already handles, where themes, video and course content cause most failures, how…
Read articleSkip the trial and error. Get specialist LifterLMS help and ship faster.