| name | frappe-ops-upgrades |
| description | Use when upgrading Frappe/ERPNext between major versions (v14 to v15, v15 to v16), troubleshooting failed migrations, or planning rollback. Prevents broken upgrades from skipped patches, incompatible customizations, and missing pre-upgrade checks. Covers version upgrade paths, bench update, migrate command, patch troubleshooting, rollback procedures, breaking changes per version. Keywords: upgrade, migration, v14, v15, v16, bench update, bench migrate, rollback, patches, breaking changes, update failed, bench update error, migration error, patches failing, rollback after upgrade..
|
| license | MIT |
| compatibility | Claude Code, Claude.ai Projects, Claude API. Frappe v14-v16. |
| metadata | {"author":"OpenAEC-Foundation","version":"2.0"} |
Version Upgrades
Complete guide for upgrading Frappe/ERPNext between major versions, handling failed migrations, and rolling back safely.
Versions: v14 โ v15 โ v16
Quick Reference: Upgrade Commands
| Task | Command |
|---|
| Full update | bench update |
| Update specific app | bench update --pull --app erpnext |
| Switch branch | bench switch-to-branch version-15 frappe erpnext |
| Run migrations only | bench --site mysite migrate |
| Check migration readiness | bench --site mysite ready-for-migration |
| Backup before upgrade | bench --site mysite backup |
| Restore from backup | bench --site mysite restore /path/to/backup.sql.gz |
| Re-run failed patch | Add #YYYY-MM-DD suffix in patches.txt |
Decision Tree: Upgrade Strategy
Need to upgrade?
โโโ Single minor version bump (e.g., v15.10 โ v15.20)?
โ โโโ YES โ Run `bench update` directly
โโโ Major version jump (e.g., v14 โ v15)?
โ โโโ Have custom apps?
โ โ โโโ YES โ Test on staging FIRST, check breaking changes
โ โ โโโ NO โ Follow standard upgrade path
โ โโโ Multiple major versions (v14 โ v16)?
โ โโโ ALWAYS upgrade one version at a time: v14 โ v15 โ v16
โโโ Production environment?
โโโ YES โ ALWAYS test on staging clone first
โโโ NO โ Proceed with standard upgrade
Pre-Upgrade Checklist
ALWAYS complete these steps before ANY major version upgrade:
- Full backup โ
bench --site mysite backup --with-files
- Test on staging โ Clone production to a staging bench and test there first
- Check breaking changes โ Review the breaking changes section below
- Audit custom apps โ Run custom apps against new version's API changes
- Check Python/Node versions โ v15 requires Node 18+; v16 requires Node 24+, Python 3.14+
- Disable scheduler โ
bench --site mysite scheduler disable
- Check pending jobs โ
bench --site mysite ready-for-migration
- Read release notes โ Check GitHub release notes for each version
Standard Upgrade Process
Step-by-Step
bench backup-all-sites
bench switch-to-branch version-15 frappe erpnext
bench update
bench --site mysite migrate
bench version
What bench update Executes (In Order)
- Backup all sites
- Pull latest code for all apps (
git pull)
- Install Python requirements (
pip install)
- Install Node requirements (
yarn install)
- Build static assets (
bench build)
- Run migrations on all sites (
bench migrate)
- Restart bench processes
v14 โ v15 Breaking Changes
Environment Requirements
| Requirement | v14 | v15 |
|---|
| Node.js | v14+ | v18+ |
| Python packaging | setup.py | pyproject.toml |
Backend Breaking Changes
db.set() removed โ Use doc.db_set() instead
db.sql() parameters removed โ as_utf8 and formatted no longer accepted
db.set_value() for Singles โ Use frappe.db.set_single_value() instead
job_name deprecated โ Use job_id parameter in enqueue()
frappe.new_doc() arguments โ parent_doc, parentfield, as_dict MUST be keyword args
frappe.get_installed_apps() โ No longer accepts sort or frappe_last args
- Method override order reversed โ Last override now takes precedence
- Timezone functions renamed โ
convert_utc_to_user_timezone โ convert_utc_to_system_timezone
Frontend Breaking Changes
- Vue 2 โ Vue 3 โ All Vue components MUST be migrated
- Window globals removed โ
get_today โ frappe.datetime.get_today, user โ frappe.session.user
this in Client Scripts โ Local scope access no longer supported
- Image lazy loading โ Replace
website-image-lazy class with native loading="lazy"
Security Changes
- Server Scripts disabled by default โ Enable:
bench set-config -g server_script_enabled 1
- "Desk User" role added โ Replaces "All" role for desk user permissions
currentsite.txt removed โ Use bench use sitename or FRAPPE_SITE env var
Removed Features
- Event Streaming moved to separate app
- Cordova support removed
setup.py removed (use pyproject.toml)
--make_copy and --restore build flags removed (use --hard-link)
See breaking-changes.md for the complete list.
v15 โ v16 Breaking Changes
Environment Requirements
| Requirement | v15 | v16 |
|---|
| Node.js | v18+ | v24+ |
| Python | 3.10+ | 3.14+ |
Backend Breaking Changes
- Default sort order changed โ
creation instead of modified for all list queries
has_permission hooks โ MUST return explicit True; None no longer accepted
frappe.get_doc(doctype, name, field=value) โ No longer updates values
- DB commits in document hooks โ No longer allowed to prevent data integrity issues
frappe.sendmail(now=True) โ No longer commits transactions implicitly
db.get_value() for Singles โ Now returns proper types instead of strings
- State-changing methods require POST โ
/api/method/logout, /api/method/upload_file, etc.
Separated Modules (Install Separately)
- Energy Points โ
frappe/eps
- Newsletter โ
frappe/newsletter
- Backup Integrations โ
frappe/offsite_backups
- Blog โ
frappe/blog
Frontend Breaking Changes
- Report/Dashboard/Page JS evaluated as IIFEs (no global scope pollution)
- Awesome Bar redesigned, moved to sidebar (
Cmd+K)
- List view right sidebar removed
/apps endpoint deprecated; /app reroutes to /desk
Configuration Changes
- Site config cached for up to one minute (changes not immediate)
- Country field requires valid ISO 3166 ALPHA-2 code
bench version output format changed to "plain" (use -f legacy for old format)
override_doctype hook classes MUST inherit from the overridden class
See breaking-changes.md for the complete list.
Patch System
How Patches Work
Patches are one-off data migration scripts that run during bench migrate. They are defined in each app's patches.txt file.
patches.txt Format [v14+]
[pre_model_sync]
myapp.patches.v15_0.prepare_data_for_migration
[post_model_sync]
myapp.patches.v15_0.migrate_data_to_new_fields
Patch Execution Rules
- Patches run in the order defined in
patches.txt
- Each patch runs exactly ONCE โ tracked in the
__patches table
- To re-run a patch, append a date comment:
myapp.patches.v15_0.fix #2025-03-20
- One-off statements:
execute:frappe.delete_doc('Page', 'old_page', ignore_missing=True)
Writing a Patch
import frappe
def execute():
frappe.reload_doc("module_name", "doctype", "doctype_name")
frappe.db.sql("""
UPDATE `tabSales Invoice`
SET new_field = old_field
WHERE old_field IS NOT NULL
""")
Debugging Stuck Patches
bench --site mysite console
>>> frappe.db.sql("SELECT * FROM __patches WHERE patch LIKE '%stuck_patch%'")
>>> frappe.db.sql("DELETE FROM __patches WHERE patch = 'myapp.patches.v15_0.broken_patch'")
>>> frappe.db.commit()
bench --site mysite migrate
Rollback Procedure
Immediate Rollback (Within Hours)
bench stop
bench --site mysite restore /path/to/pre-upgrade-backup.sql.gz \
--with-public-files /path/to/files.tar \
--with-private-files /path/to/private-files.tar
bench switch-to-branch version-14 frappe erpnext
bench setup requirements
bench build
bench start
Critical Rules for Rollback
- ALWAYS keep pre-upgrade backups for at least 7 days
- NEVER run
bench migrate after restoring to old branch โ schema is already correct
- ALWAYS restore files alongside database โ file references may break otherwise
- NEVER attempt rollback after users have created new data on the upgraded version
Frappe Packages: Moving Customizations Between Sites
Frappe Packages (v14+) are lightweight UI-built applications โ bundles of Custom Module Defs distributed as .tar.gz tarballs. For Custom Fields, Property Setters, and DocPerms on standard DocTypes, use Fixtures instead.
Quick Reference: Package vs Fixtures vs App
| Mechanism | Use When | CLI Command |
|---|
| Package | UI-built DocTypes, Scripts, Web Pages | UI only (Package Import/Release) |
| Fixtures | Custom Fields, Property Setters, DocPerms | bench --site mysite export-fixtures |
| Frappe App | Full development workflow, CI/CD, tests | bench get-app, bench install-app |
Package Workflow (UI-Based)
- Create a Package document โ assign Custom Module Defs to it
- Create a Package Release โ exports to
[bench]/sites/[site]/packages/ as [package]-[version].tar.gz
- On target site, create Package Import โ attach tarball, check Activate
- System migrates data like an app migration; use Force to overwrite existing files
Fixtures Workflow (CLI-Based)
fixtures = [
"Custom Field",
"Property Setter",
{"dt": "Client Script", "filters": [["module", "=", "My Module"]]}
]
bench --site mysite export-fixtures --app myapp
NEVER use Packages to modify standard/core DocTypes โ use a Frappe App with Fixtures.
See frappe-packages.md for the complete reference including decision trees, limitations, and best practices.
Custom App Compatibility Checks
Before upgrading, audit each custom app:
- Check deprecated APIs โ Search for removed functions listed in breaking changes
- Check
setup.py โ Must migrate to pyproject.toml for v15+
- Check Vue components โ Must be Vue 3 compatible for v15+
- Check
patches.txt โ Ensure patches use [pre_model_sync]/[post_model_sync] sections [v14+]
- Check hooks.py โ Verify no removed hooks are used
- Run tests โ
bench --site test_site run-tests --app myapp
Decision Tree: In-Place vs Fresh Install
Choosing upgrade strategy:
โโโ Small site (< 10 GB database)?
โ โโโ In-place upgrade is usually fine
โโโ Large site (> 50 GB database)?
โ โโโ Many custom apps? โ Fresh install + data migration
โ โโโ Standard apps only? โ In-place with extended downtime window
โโโ Skipping multiple versions (v13 โ v15)?
โ โโโ ALWAYS fresh install โ sequential upgrades are too risky
โโโ Critical production with zero-downtime requirement?
โโโ Fresh install on parallel server + DNS switch
Version Differences Summary
| Feature | v14 | v15 | v16 |
|---|
| Python packaging | setup.py | pyproject.toml | pyproject.toml |
| Vue version | Vue 2 | Vue 3 | Vue 3 |
| Node.js minimum | v14 | v18 | v24 |
| Python minimum | 3.8 | 3.10 | 3.14 |
| Server Scripts | Enabled | Disabled default | Disabled default |
| Default sort | modified | modified | creation |
| patches.txt sections | Yes | Yes | Yes |
| Workspace sidebar | No | No | Yes |
| Separated modules | โ | Event Streaming | Blog, Newsletter, EPS |
Reference Files