> 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.
npx skills add https://github.com/Impertio-Studio/Frappe_Claude_Skill_Package --skill frappe-ops-upgrades
Complete guide for upgrading Frappe/ERPNext between major versions, handling failed migrations, and rolling back safely.
Versions: v14 → v15 → v16
| 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 |
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
ALWAYS complete these steps before ANY major version upgrade:
bench --site mysite backup --with-filesbench --site mysite scheduler disablebench --site mysite ready-for-migration# 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
bench update Executes (In Order)git pull)pip install)yarn install)bench build)bench migrate)| Requirement | v14 | v15 |
|-------------|-----|-----|
| Node.js | v14+ | v18+ |
| Python packaging | setup.py | pyproject.toml |
db.set() removed — Use doc.db_set() insteaddb.sql() parameters removed — as_utf8 and formatted no longer accepteddb.set_value() for Singles — Use frappe.db.set_single_value() insteadjob_name deprecated — Use job_id parameter in enqueue()frappe.new_doc() arguments — parent_doc, parentfield, as_dict MUST be keyword argsfrappe.get_installed_apps() — No longer accepts sort or frappe_last argsconvert_utc_to_user_timezone → convert_utc_to_system_timezoneget_today → frappe.datetime.get_today, user → frappe.session.userthis in Client Scripts — Local scope access no longer supportedwebsite-image-lazy class with native loading="lazy"bench set-config -g server_script_enabled 1currentsite.txt removed — Use bench use sitename or FRAPPE_SITE env varsetup.py removed (use pyproject.toml)--make_copy and --restore build flags removed (use --hard-link)See breaking-changes.md for the complete list.
| Requirement | v15 | v16 |
|-------------|-----|-----|
| Node.js | v18+ | v24+ |
| Python | 3.10+ | 3.14+ |
creation instead of modified for all list querieshas_permission hooks — MUST return explicit True; None no longer acceptedfrappe.get_doc(doctype, name, field=value) — No longer updates valuesfrappe.sendmail(now=True) — No longer commits transactions implicitlydb.get_value() for Singles — Now returns proper types instead of strings/api/method/logout, /api/method/upload_file, etc.frappe/epsfrappe/newsletterfrappe/offsite_backupsfrappe/blogCmd+K)/apps endpoint deprecated; /app reroutes to /deskbench version output format changed to "plain" (use -f legacy for old format)override_doctype hook classes MUST inherit from the overridden classSee breaking-changes.md for the complete list.
Patches are one-off data migration scripts that run during bench migrate. They are defined in each app's patches.txt file.
[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
patches.txt__patches tablemyapp.patches.v15_0.fix #2025-03-20execute:frappe.delete_doc('Page', 'old_page', ignore_missing=True)# 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
""")
# 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
# 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)
bench migrate after restoring to old branch — schema is already correctFrappe 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.
| 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 |
[bench]/sites/[site]/packages/ as [package]-[version].tar.gz# 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.
Before upgrading, audit each custom app:
setup.py — Must migrate to pyproject.toml for v15+patches.txt — Ensure patches use [pre_model_sync]/[post_model_sync] sections [v14+]bench --site test_site run-tests --app myappChoosing 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
| 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 |
| 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 |
Guide users through a structured workflow for co-authoring documentation. Use when user wants to write documentation, proposals, technical specs, decision docs, or similar structured content. This workflow helps users efficiently transfer context, refine content through iteration, and verify the doc works for readers. Trigger when user mentions writing docs, creating proposals, drafting specs, or similar documentation tasks.
Intelligently organizes your files and folders across your computer by understanding context, finding duplicates, suggesting better structures, and automating cleanup tasks. Reduces cognitive load and keeps your digital workspace tidy without manual effort.
Generates creative domain name ideas for your project and checks availability across multiple TLDs (.com, .io, .dev, .ai, etc.). Saves hours of brainstorming and manual checking.
You MUST use this before any creative work - creating features, building components, adding functionality, or modifying behavior. Explores user intent, requirements and design before implementation.
Implements Manus-style file-based planning for complex tasks. Creates task_plan.md, findings.md, and progress.md. Use when starting complex multi-step tasks, research projects, or any task requiring >5 tool calls.
Creative research ideation and exploration. Use for open-ended brainstorming sessions, exploring interdisciplinary connections, challenging assumptions, or identifying research gaps. Best for early-stage research planning when you do not have specific observations yet. For formulating testable hypotheses from data use hypothesis-generation.
Comprehensive GitHub project management with swarm-coordinated issue tracking, project board automation, and sprint planning
Interview the user relentlessly about a plan or design until reaching shared understanding, resolving each branch of the decision tree. Use when user wants to stress-test a plan, get grilled on their design, or mentions "grill me".
Take impertio-studio/frappe-ops-upgrades from the repository into ~/.claude/skills for personal
use, or into .claude/skills inside a project.
The agent identifies a skill by the name field in its header. Two skills with the
same name cannot sit side by side — one of them will be ignored.
The instructions reference pip.
Without those the skill loads but fails at the first command.