Frappe_Claude_Skill_Package frappe-ops-upgrades
install
source · Clone the upstream repo
git clone https://github.com/OpenAEC-Foundation/Frappe_Claude_Skill_Package
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/OpenAEC-Foundation/Frappe_Claude_Skill_Package "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/source/ops/frappe-ops-upgrades" ~/.claude/skills/openaec-foundation-frappe-claude-skill-package-frappe-ops-upgrades && rm -rf "$T"
manifest:
skills/source/ops/frappe-ops-upgrades/SKILL.mdsource content
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 | |
| Update specific app | |
| Switch branch | |
| Run migrations only | |
| Check migration readiness | |
| Backup before upgrade | |
| Restore from backup | |
| Re-run failed patch | Add 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
# 1. Backup all sites bench backup-all-sites # 2. Switch to target version branch bench switch-to-branch version-15 frappe erpnext # 3. Update (pulls code, installs deps, builds, migrates) bench update # 4. Verify bench --site mysite migrate # if not done by update bench version # confirm versions
What bench update
Executes (In Order)
bench update- 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
removed — Usedb.set()
insteaddoc.db_set()
parameters removed —db.sql()
andas_utf8
no longer acceptedformatted
for Singles — Usedb.set_value()
insteadfrappe.db.set_single_value()
deprecated — Usejob_name
parameter injob_idenqueue()
arguments —frappe.new_doc()
,parent_doc
,parentfield
MUST be keyword argsas_dict
— No longer acceptsfrappe.get_installed_apps()
orsort
argsfrappe_last- Method override order reversed — Last override now takes precedence
- Timezone functions renamed —
→convert_utc_to_user_timezoneconvert_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
→userfrappe.session.user
in Client Scripts — Local scope access no longer supportedthis- Image lazy loading — Replace
class with nativewebsite-image-lazyloading="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
removed — Usecurrentsite.txt
orbench use sitename
env varFRAPPE_SITE
Removed Features
- Event Streaming moved to separate app
- Cordova support removed
removed (usesetup.py
)pyproject.toml
and--make_copy
build flags removed (use--restore
)--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 —
instead ofcreation
for all list queriesmodified
hooks — MUST return explicithas_permission
;True
no longer acceptedNone
— No longer updates valuesfrappe.get_doc(doctype, name, field=value)- DB commits in document hooks — No longer allowed to prevent data integrity issues
— No longer commits transactions implicitlyfrappe.sendmail(now=True)
for Singles — Now returns proper types instead of stringsdb.get_value()- State-changing methods require POST —
,/api/method/logout
, etc./api/method/upload_file
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
endpoint deprecated;/apps
reroutes to/app/desk
Configuration Changes
- Site config cached for up to one minute (changes not immediate)
- Country field requires valid ISO 3166 ALPHA-2 code
output format changed to "plain" (usebench version
for old format)-f legacy
hook classes MUST inherit from the overridden classoverride_doctype
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] # Runs BEFORE schema sync — use for data prep myapp.patches.v15_0.prepare_data_for_migration [post_model_sync] # Runs AFTER schema sync — use for data that needs new schema 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
table__patches - 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
# myapp/patches/v15_0/migrate_field_data.py import frappe def execute(): # ALWAYS reload if you need the NEW schema frappe.reload_doc("module_name", "doctype", "doctype_name") # Perform data migration frappe.db.sql(""" UPDATE `tabSales Invoice` SET new_field = old_field WHERE old_field IS NOT NULL """)
Debugging Stuck Patches
# Check which patches have run bench --site mysite console >>> frappe.db.sql("SELECT * FROM __patches WHERE patch LIKE '%stuck_patch%'") # Remove a patch record to force re-run >>> frappe.db.sql("DELETE FROM __patches WHERE patch = 'myapp.patches.v15_0.broken_patch'") >>> frappe.db.commit() # Then re-run migrate bench --site mysite migrate
Rollback Procedure
Immediate Rollback (Within Hours)
# 1. Stop all processes bench stop # 2. Restore database from pre-upgrade backup 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 # 3. Switch back to previous version branch bench switch-to-branch version-14 frappe erpnext # 4. Install old dependencies bench setup requirements # 5. Build old assets bench build # 6. Start bench bench start # or: sudo bench restart (production)
Critical Rules for Rollback
- ALWAYS keep pre-upgrade backups for at least 7 days
- NEVER run
after restoring to old branch — schema is already correctbench migrate - 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 | |
| Frappe App | Full development workflow, CI/CD, tests | , |
Package Workflow (UI-Based)
- Create a Package document → assign Custom Module Defs to it
- Create a Package Release → exports to
as[bench]/sites/[site]/packages/[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)
# hooks.py — define what to export fixtures = [ "Custom Field", "Property Setter", {"dt": "Client Script", "filters": [["module", "=", "My Module"]]} ]
# Export fixtures to JSON in your app bench --site mysite export-fixtures --app myapp # Fixtures auto-sync on: bench --site mysite migrate
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
— Must migrate tosetup.py
for v15+pyproject.toml - Check Vue components — Must be Vue 3 compatible for v15+
- Check
— Ensure patches usepatches.txt
/[pre_model_sync]
sections [v14+][post_model_sync] - 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
| File | Contents |
|---|---|
| examples.md | Complete upgrade workflow examples |
| anti-patterns.md | Common upgrade mistakes and fixes |
| breaking-changes.md | Detailed breaking changes per version |
| frappe-packages.md | Packages, fixtures, and moving customizations between sites |