What actually breaks when you upgrade ERPNext to v15
Six migrations in, the failures cluster in the same four places. None of them are in the release notes.
The v15 release notes are accurate and not especially useful. They tell you what changed in the framework. They don't tell you what will break in a five-year-old production instance with eleven custom apps, and that's the only question anyone actually has.
Here's where our last six upgrades went wrong.
Custom apps pinned to an old Frappe API
This is the big one, and it's roughly seventy percent of the total pain. Apps written against v13 or early v14 tend to call framework internals that moved or vanished. The failures are rarely loud — the app installs fine and then throws on a specific document type at 2am.
The fix isn't clever, it's just work: read every custom app, grep for the deprecated calls, run the app's test suite against a v15 staging bench. If an app has no tests, that's your first invoice.
Print formats with inline Jinja
Custom print formats that embed Jinja against document fields break when field names change or when a link field's fetch behaviour shifts. Finance notices this immediately, because the invoice they print on Sunday morning is suddenly missing the VAT breakdown.
Enumerate the print formats before the upgrade. There are always more than anyone remembers.
The scheduler
Background jobs that were quietly failing on v14 often start failing loudly on v15, which is an improvement but doesn't feel like one at the time. Check the scheduler log for the two weeks before you upgrade — you'll usually find something that's been broken for months.
Database collation on older instances
Instances originally created years ago sometimes carry a collation that v15's migrations don't handle cleanly. This surfaces as a migration failure partway through, at which point you're restoring from backup.
Check the collation first. It takes a minute and saves a night.
The actual process
What we do now, in order:
- Clone production to a staging bench.
- Run the upgrade on staging and capture every error.
- Fix, re-clone, run again — until it's clean twice in a row.
- Hand staging to the client for a week of real use.
- Schedule the production cutover with a restore point taken immediately before.
Two clean runs, not one. The first clean run is often luck.