First of all
Thank you for building and maintaining Frappe LMS — it's a great project and we really appreciate the work that goes into it. We're running it in production and love the platform.
Summary
After running easy-install.py upgrade, the ghcr.io/frappe/lms:stable image was updated from Frappe v15 to Frappe v16.17.0. Unfortunately this caused a complete service outage for our production installation. We'd like to share the full failure chain in hopes it helps improve the upgrade process.
Environment
- Deploy method:
easy-install.py
- OS: Ubuntu 24.04
- Previous working state: Frappe 15.101.0, LMS 2.45.1, Python 3.11
- State after update: Frappe 16.17.0, Python 3.14
Issue 1: stable image does not include the LMS app
After pulling the new stable image, the LMS app is absent from the bench:
$ docker exec backend ls /home/frappe/frappe-bench/apps/
frappe
# lms is not present
Running bench migrate immediately fails:
ModuleNotFoundError: No module named 'lms'
It seems the new image may have been published without the LMS app bundled, which makes it unusable for LMS deployments out of the box.
Issue 2: Manual LMS installation requires payments — undocumented dependency
Following the natural workaround of manually installing LMS via bench get-app lms fails at the install step:
$ bench --site lms.example.com install-app lms
An error occurred while installing lms: No module named 'payments'
The current LMS branch requires payments as a dependency. This dependency:
- Does not appear to be documented in the installation guide
- Was not required in v15
- Is not included in the
stable image
It would be helpful to either include payments in the image or document it as a required step.
Issue 3: easy-install.py upgrade has no major version compatibility check
The upgrade script currently:
- Pulls the new image
- Immediately runs
bench --site all migrate
- Does not check for Frappe major version compatibility beforehand
By the time the incompatibility error appears, the database has already been partially modified, making a clean rollback difficult. A simple version check before migration would prevent this situation entirely.
Issue 4: Database becomes inconsistent after failed upgrade + rollback
When attempting to install payments as a workaround for Issue 2, it partially modifies the database:
-- payments added to installed_apps in tabDefaultValue
["frappe", "lms", "payments"]
-- Records created in tabInstalled Application
payments | 0.0.1
-- Records created in tabModule Def
Payment Gateways | payments
Payments | payments
After rolling back to the cached v15 image, bench migrate continues to fail because v15 does not have payments, but the database now expects it.
We were able to recover by manually cleaning up these records:
UPDATE `tabDefaultValue`
SET defvalue='["frappe", "lms"]'
WHERE defkey='installed_apps';
DELETE FROM `tabInstalled Application` WHERE app_name='payments';
DELETE FROM `tabModule Def` WHERE app_name='payments';
It would be great if the upgrade script could handle this kind of rollback automatically, or at least document the recovery steps.
Issue 5: No versioned image tags for major Frappe versions
The stable tag currently moves between major Frappe versions (v15 → v16) without any announcement or warning. Having versioned tags like stable-v15 or stable-v16 would allow users to control when they migrate between major versions and follow a proper migration guide before doing so.
Suggestions
We understand this is a complex project to maintain. A few things that would significantly improve the upgrade experience:
- Ensure the
stable image always includes a working LMS installation
- Consider versioned tags (
stable-v15, stable-v16) for major version control
- Add a Frappe major version compatibility check to
easy-install.py upgrade before running migrations
- Publish a v15 → v16 migration guide when the
stable tag moves to v16
- Document
payments as a dependency if it's now required
First of all
Thank you for building and maintaining Frappe LMS — it's a great project and we really appreciate the work that goes into it. We're running it in production and love the platform.
Summary
After running
easy-install.py upgrade, theghcr.io/frappe/lms:stableimage was updated from Frappe v15 to Frappe v16.17.0. Unfortunately this caused a complete service outage for our production installation. We'd like to share the full failure chain in hopes it helps improve the upgrade process.Environment
easy-install.pyIssue 1:
stableimage does not include the LMS appAfter pulling the new
stableimage, the LMS app is absent from the bench:Running
bench migrateimmediately fails:It seems the new image may have been published without the LMS app bundled, which makes it unusable for LMS deployments out of the box.
Issue 2: Manual LMS installation requires
payments— undocumented dependencyFollowing the natural workaround of manually installing LMS via
bench get-app lmsfails at the install step:The current LMS branch requires
paymentsas a dependency. This dependency:stableimageIt would be helpful to either include
paymentsin the image or document it as a required step.Issue 3:
easy-install.py upgradehas no major version compatibility checkThe upgrade script currently:
bench --site all migrateBy the time the incompatibility error appears, the database has already been partially modified, making a clean rollback difficult. A simple version check before migration would prevent this situation entirely.
Issue 4: Database becomes inconsistent after failed upgrade + rollback
When attempting to install
paymentsas a workaround for Issue 2, it partially modifies the database:After rolling back to the cached v15 image,
bench migratecontinues to fail because v15 does not havepayments, but the database now expects it.We were able to recover by manually cleaning up these records:
It would be great if the upgrade script could handle this kind of rollback automatically, or at least document the recovery steps.
Issue 5: No versioned image tags for major Frappe versions
The
stabletag currently moves between major Frappe versions (v15 → v16) without any announcement or warning. Having versioned tags likestable-v15orstable-v16would allow users to control when they migrate between major versions and follow a proper migration guide before doing so.Suggestions
We understand this is a complex project to maintain. A few things that would significantly improve the upgrade experience:
stableimage always includes a working LMS installationstable-v15,stable-v16) for major version controleasy-install.py upgradebefore running migrationsstabletag moves to v16paymentsas a dependency if it's now required