
Frappe Agent Migrator
- 61 installs
- 159 repo stars
- Updated July 8, 2026
- openaec-foundation/erpnext_anthropic_claude_development_skill_package
Plans Frappe/ERPNext version migrations by detecting breaking and deprecated APIs across v14-v16 and generating a migration checklist with fixes.
About
A migration skill that plans and executes Frappe/ERPNext major-version upgrades by scanning for breaking and deprecated APIs. A developer uses it when upgrading a Frappe app between versions and needs to catch compatibility issues before updating.
- Detects breaking API changes across Frappe v14/v15/v16
- Generates migration checklist and automatic fix suggestions for deprecated APIs
Frappe Agent Migrator by the numbers
- 61 all-time installs (skills.sh)
- Ranked #3,152 of 4,347 Backend & APIs skills by installs in the Skillselion catalog
- Data as of Aug 5, 2026 (Skillselion catalog sync)
npx skills add https://github.com/openaec-foundation/erpnext_anthropic_claude_development_skill_package --skill frappe-agent-migratorAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 61 |
|---|---|
| repo stars | ★ 159 |
| Last updated | July 8, 2026 |
| Repository | openaec-foundation/erpnext_anthropic_claude_development_skill_package ↗ |
What it does
Plans Frappe/ERPNext version migrations by detecting breaking and deprecated APIs across v14-v16 and generating a migration checklist with fixes.
Files
Version Migration Assistant
Systematically plans and executes Frappe/ERPNext version migrations by analyzing breaking changes, scanning custom code for compatibility issues, and generating migration plans.
Purpose: Prevent failed migrations by detecting every breaking change BEFORE upgrading.
When to Use This Agent
MIGRATION TRIGGER
|
+-- Planning a version upgrade
| "We need to go from v14 to v15"
| --> USE THIS AGENT
|
+-- Post-upgrade errors
| "Everything broke after bench update"
| --> USE THIS AGENT (Step 2-5 for diagnosis)
|
+-- Checking custom app compatibility
| "Will our custom app work on v16?"
| --> USE THIS AGENT (Step 3 for code scan)
|
+-- Already mid-migration with issues
| "bench migrate fails with errors"
| --> USE THIS AGENT + frappe-agent-debuggerMigration Workflow
STEP 1: IDENTIFY MIGRATION PATH
Source version → Target version (NEVER skip major versions)
STEP 2: CHECK BREAKING CHANGES
Apply breaking changes database for each version jump
STEP 3: SCAN CUSTOM CODE
Grep for deprecated patterns in all custom apps
STEP 4: GENERATE MIGRATION PLAN
Backup → Staging → Test → Production sequence
STEP 5: GENERATE PATCH LIST
Specific code changes needed per custom appSee references/workflow.md for detailed steps.
Step 1: Migration Path Rules
NEVER skip major versions. ALWAYS migrate sequentially:
| Source | Target | Path |
|---|---|---|
| v14 | v15 | v14 → v15 |
| v14 | v16 | v14 → v15 → v16 |
| v15 | v16 | v15 → v16 |
Version Identification
# Check current versions
bench version
# Output shows: frappe X.Y.Z, erpnext X.Y.Z
# Check available versions
cd apps/frappe && git tag | grep "^v1[456]" | tail -5Step 2: Breaking Changes Summary
v14 → v15 Breaking Changes
| Category | Change | Impact | Detection Pattern |
|---|---|---|---|
| Scheduler | Tick interval 240s → 60s | Jobs may run more frequently | Review scheduler_events |
| Background Jobs | job_id deduplication added | Duplicate jobs now prevented | Check frappe.enqueue() calls |
| Web Views | Workspace replaces Module Def pages | Custom module pages break | Grep for Module Def references |
| Print Format | HTML to PDF engine changes | Print layout differences | Test all print formats |
| Database | MariaDB 10.6+ required | Server prerequisite | Check mysql --version |
| Python | Python 3.10+ required | Syntax/library compatibility | Check python3 --version |
| API | frappe.client.get_list signature change | Custom API calls may fail | Grep for frappe.client.get_list |
| Permissions | Stricter permission checks on API | Guest access may break | Check allow_guest=True usage |
| Assets | New frontend build system | Custom JS bundles may break | Test bench build |
| Hooks | boot_session hook changes | Custom boot data may fail | Grep for boot_session |
| Naming | Some naming series changes | Document names may differ | Review autoname settings |
| Report | Report Builder changes | Custom reports may need updates | Test all Script Reports |
v15 → v16 Breaking Changes
| Category | Change | Impact | Detection Pattern |
|---|---|---|---|
| DocType Extension | extend_doctype_class replaces doc_events override | Controller overrides need refactoring | Grep for doc_events with method override |
| Type Annotations | Type hints now best practice | Code style change | Not breaking, but recommended |
| Chrome PDF | New PDF engine (Chrome-based) | Print format rendering changes | Test all print formats |
| Data Masking | New privacy feature | PII fields need configuration | Review sensitive fields |
| UUID Naming | New uuid naming rule | Naming logic changes | Check autoname settings |
| Python | Python 3.11+ required | Library compatibility | Check python3 --version |
| Node.js | Node 18+ required | Build system prerequisite | Check node --version |
| Redis | Redis 7+ required | Cache/queue compatibility | Check redis-server --version |
| Deprecated APIs | Several APIs removed | Code using removed APIs fails | See breaking-changes.md |
| Workflow | Workflow engine updates | Custom workflow states may need review | Test all workflows |
| Portal | Portal page rendering changes | Custom portal pages may break | Test all portal pages |
| Background Jobs | RQ version upgrade | Job serialization changes | Test background jobs |
See references/breaking-changes.md for complete details.
Step 3: Deprecated Pattern Detection
ALWAYS scan custom app code for these patterns:
v14 → v15 Deprecated Patterns
# Run these grep commands in apps/{your_app}/ directory:
# 1. Old-style module page references
grep -rn "Module Def" --include="*.py" --include="*.json"
# 2. Old scheduler API
grep -rn "frappe.utils.scheduler" --include="*.py"
# 3. Deprecated client API
grep -rn "frappe.set_route\|cur_page\|page_container" --include="*.js"
# 4. Old-style print format
grep -rn "frappe.get_print\|standard_format" --include="*.py"
# 5. Deprecated database methods
grep -rn "frappe.db.sql_list\|frappe.db.sql_ddl" --include="*.py"v15 → v16 Deprecated Patterns
# Run these grep commands in apps/{your_app}/ directory:
# 1. doc_events that should use extend_doctype_class
grep -rn "doc_events" hooks.py
# 2. Old-style controller override
grep -rn "override_doctype_class" --include="*.py"
# 3. Deprecated frappe.utils methods
grep -rn "frappe.utils.now_datetime\b" --include="*.py"
# 4. Old print format API
grep -rn "frappe.utils.pdf\|get_pdf" --include="*.py"
# 5. Removed API calls
grep -rn "frappe.get_hooks\b.*boot_session" --include="*.py"
# 6. Missing type annotations (warning, not error)
grep -rn "def .*whitelist" --include="*.py"Step 4: Migration Plan Template
ALWAYS generate a migration plan in this format:
## Migration Plan: v{source} → v{target}
### Prerequisites
- [ ] Python version: {required}
- [ ] Node.js version: {required}
- [ ] MariaDB version: {required}
- [ ] Redis version: {required}
- [ ] Disk space: minimum 2x current DB size
### Phase 1: Preparation (Day 1)
1. Full backup: `bench --site {site} backup --with-files`
2. Document current state: `bench version > pre-migration-versions.txt`
3. List all custom apps: `bench --site {site} list-apps`
4. Run deprecated pattern scan (Step 3)
5. Fix all detected issues in custom apps
### Phase 2: Staging (Day 2-3)
1. Clone production to staging environment
2. Restore backup on staging: `bench --site staging restore {backup}`
3. Switch branch: `bench switch-to-branch version-{target} frappe erpnext`
4. Run migration: `bench --site staging migrate`
5. Run full test suite on staging
### Phase 3: Testing (Day 4-5)
- [ ] All DocTypes load correctly
- [ ] All print formats render correctly
- [ ] All workflows transition correctly
- [ ] All scheduled jobs execute correctly
- [ ] All custom reports generate correctly
- [ ] All API endpoints respond correctly
- [ ] All user permissions work correctly
- [ ] Performance is acceptable (page load < 3s)
### Phase 4: Production (Day 6)
1. Schedule maintenance window
2. Enable maintenance mode: `bench --site {site} set-maintenance-mode on`
3. Final backup: `bench --site {site} backup --with-files`
4. Switch branch: `bench switch-to-branch version-{target} frappe erpnext`
5. Run migration: `bench --site {site} migrate`
6. Run `bench build --production`
7. Restart: `bench restart` (or `sudo supervisorctl restart all`)
8. Disable maintenance mode: `bench --site {site} set-maintenance-mode off`
9. Verify (Phase 3 checklist again)
### Rollback Plan
1. Stop all services: `sudo supervisorctl stop all`
2. Restore backup: `bench --site {site} restore {backup_path}`
3. Switch back: `bench switch-to-branch version-{source} frappe erpnext`
4. Run migration: `bench --site {site} migrate`
5. Rebuild: `bench build --production`
6. Restart: `sudo supervisorctl restart all`Step 5: Custom App Patch List
For each deprecated pattern found in Step 3, generate a specific fix:
| File | Line | Current Code | Required Change | Breaking? |
|---|---|---|---|---|
{file} | {line} | {old_pattern} | {new_pattern} | Yes/No |
Common Patches (v14 → v15)
| Pattern | Replace With |
|---|---|
frappe.db.sql_list(...) | frappe.db.get_all(..., pluck="name") |
Module Def page references | Workspace configuration |
cur_page JS references | frappe.router API |
| Old scheduler tick assumptions | Review timing for 60s interval |
Common Patches (v15 → v16)
| Pattern | Replace With |
|---|---|
doc_events controller override | extend_doctype_class in hooks.py |
Missing super() in overrides | Add super().method() call |
frappe.utils.pdf.get_pdf() | Updated PDF API |
| No type annotations | Add type hints to public methods |
Agent Output Format
ALWAYS produce migration output in this format:
## Migration Assessment
### Version Path
{source} → {target} (via {intermediate versions if any})
### Prerequisites Status
| Requirement | Current | Required | Status |
|-------------|---------|----------|--------|
| Python | {ver} | {ver} | OK/FAIL |
| Node.js | {ver} | {ver} | OK/FAIL |
| MariaDB | {ver} | {ver} | OK/FAIL |
### Breaking Changes Found: {count}
[List from Step 2]
### Custom Code Issues Found: {count}
[Table from Step 3 scan]
### Migration Plan
[From Step 4]
### Patch List
[From Step 5]
### Risk Assessment
| Risk | Likelihood | Impact | Mitigation |
|------|-----------|--------|------------|
### Estimated Timeline
Preparation: {days} | Staging: {days} | Testing: {days} | Production: {hours}
### Referenced Skills
- `frappe-ops-upgrades`: Version upgrade procedures
- `frappe-ops-backup`: Backup and restore
- `frappe-agent-debugger`: For post-migration error diagnosisSee references/checklists.md for complete migration checklists. See references/breaking-changes.md for full breaking changes database.
Breaking Changes Database
v14 → v15 Breaking Changes (Detailed)
1. Scheduler Tick Interval Change
- Before: Default scheduler tick every 240 seconds
- After: Default scheduler tick every 60 seconds
- Impact: Scheduled tasks run 4x more frequently
- Fix: Review
scheduler_eventsin hooks.py; add deduplication logic if tasks are not idempotent - Detection:
grep -rn "scheduler_events" hooks.py
2. Background Job Deduplication
- Before: Same job could be enqueued multiple times
- After:
job_idparameter enables deduplication; duplicate jobs are silently dropped - Impact: Code relying on multiple identical jobs executing will behave differently
- Fix: Review
frappe.enqueue()calls; ensurejob_idis set correctly or omitted - Detection:
grep -rn "frappe.enqueue" --include="*.py"
3. Workspace Replaces Module Def Pages
- Before: Module pages defined via Module Def
- After: Workspace DocType replaces Module Def pages
- Impact: Custom module pages will not display
- Fix: Migrate module pages to Workspace configuration
- Detection:
grep -rn "Module Def" --include="*.py" --include="*.json"
4. Print Format Engine Changes
- Before: wkhtmltopdf used for all PDF generation
- After: Updated PDF generation pipeline
- Impact: Print format layouts may render differently
- Fix: Test all print formats on staging; adjust CSS/HTML as needed
- Detection: Visual inspection required
5. MariaDB 10.6+ Required
- Before: MariaDB 10.3+ supported
- After: MariaDB 10.6+ required
- Impact: Server must be upgraded before Frappe upgrade
- Fix: Upgrade MariaDB to 10.6+ before starting migration
- Detection:
mysql --version
6. Python 3.10+ Required
- Before: Python 3.8+ supported
- After: Python 3.10+ required
- Impact: Some Python 3.8/3.9 syntax patterns may differ
- Fix: Upgrade Python; check for deprecated stdlib usage
- Detection:
python3 --version
7. Client API Changes
- Before:
frappe.set_route()with different signature - After: Router API updated
- Impact: Custom JavaScript navigation code may break
- Fix: Update to new
frappe.routerAPI - Detection:
grep -rn "frappe.set_route\|cur_page" --include="*.js"
8. Stricter Permission Checks on API
- Before: Some API endpoints accessible without explicit permission
- After: Stricter permission validation on all API calls
- Impact: Guest or low-privilege API calls may fail
- Fix: Add
allow_guest=Truewhere needed; verify@frappe.whitelist()decorators - Detection:
grep -rn "frappe.whitelist" --include="*.py"
9. Frontend Build System Changes
- Before: Older webpack/rollup configuration
- After: Updated build toolchain
- Impact: Custom JS bundles may need rebuild configuration
- Fix: Update
package.jsonand build scripts; runbench build - Detection:
bench build --verbose(check for errors)
10. Boot Session Hook Changes
- Before:
boot_sessionhook with certain signature - After: Updated boot session mechanism
- Impact: Custom boot data injection may fail
- Fix: Update boot session hooks to new signature
- Detection:
grep -rn "boot_session" hooks.py
11. Database Query API Changes
- Before:
frappe.db.sql_list()andfrappe.db.sql_ddl()available - After: Deprecated in favor of
frappe.db.get_all()withpluck - Impact: Code using deprecated methods may fail
- Fix: Replace with modern equivalents
- Detection:
grep -rn "sql_list\|sql_ddl" --include="*.py"
12. Report Builder Updates
- Before: Older report rendering API
- After: Updated Report Builder with new API
- Impact: Custom Script Reports may need query/column updates
- Fix: Test all reports; update
execute()function if needed - Detection: Test each report individually
---
v15 → v16 Breaking Changes (Detailed)
1. extend_doctype_class (New Pattern)
- Before: Override controllers via
doc_eventsin hooks.py - After:
extend_doctype_classenables proper class inheritance - Impact: Old pattern still works but new pattern is preferred; mixins MUST call
super() - Fix: Refactor controller overrides to use
extend_doctype_class - Detection:
grep -rn "doc_events" hooks.py(look for method overrides)
2. Chrome-Based PDF Rendering
- Before: wkhtmltopdf for PDF generation
- After: Chrome/Chromium-based PDF rendering
- Impact: Print format CSS and layout rendering changes
- Fix: Test all print formats; adjust CSS for Chrome rendering
- Detection: Visual inspection of all print formats
3. Data Masking Feature
- Before: No built-in PII masking
- After:
mask_withfield option in DocType JSON - Impact: Sensitive fields should be configured for masking
- Fix: Add
mask_withto PII fields (email, phone, etc.) - Detection: Review DocType JSON for sensitive fields
4. UUID Naming Rule
- Before: Naming rules: autoincrement, hash, expression, field, series
- After: New
uuidnaming rule option - Impact: New DocTypes can use UUID; migration does not auto-convert
- Fix: Optionally adopt UUID naming for new DocTypes
- Detection: No action required for existing DocTypes
5. Python 3.11+ Required
- Before: Python 3.10+ supported
- After: Python 3.11+ required
- Impact: Some library compatibility changes
- Fix: Upgrade Python to 3.11+
- Detection:
python3 --version
6. Node.js 18+ Required
- Before: Node 16+ supported
- After: Node 18+ required
- Impact: Build system requires newer Node
- Fix: Upgrade Node.js to 18+ (use nvm)
- Detection:
node --version
7. Redis 7+ Required
- Before: Redis 6+ supported
- After: Redis 7+ required
- Impact: Cache and queue operations
- Fix: Upgrade Redis to 7+
- Detection:
redis-server --version
8. Type Annotations Best Practice
- Before: Type hints optional
- After: Type annotations recommended for all public methods
- Impact: Not breaking but strongly encouraged
- Fix: Add type hints to
@frappe.whitelist()and public methods - Detection:
grep -rn "def.*whitelist" --include="*.py"(check for missing hints)
9. Deprecated API Removals
- Before: Various deprecated APIs still functional
- After: Some deprecated APIs removed entirely
- Impact: Code using removed APIs will crash
- Fix: Replace with current equivalents (see list below)
- Detection: Grep for each deprecated pattern
10. Workflow Engine Updates
- Before: Workflow with specific state handling
- After: Updated workflow transition logic
- Impact: Custom workflow state handlers may need review
- Fix: Test all workflows on staging
- Detection:
frappe.get_all("Workflow", fields=["name", "document_type"])
11. Portal Page Rendering
- Before: Portal pages with certain template engine
- After: Updated portal rendering
- Impact: Custom portal templates may render differently
- Fix: Test all portal pages; adjust templates
- Detection:
grep -rn "website_route_rules\|get_website_page" --include="*.py"
12. RQ Version Upgrade
- Before: Older RQ (Redis Queue) version
- After: RQ upgraded with serialization changes
- Impact: Background job argument serialization may change
- Fix: Ensure job arguments are simple types (str, int, float, dict, list)
- Detection:
grep -rn "frappe.enqueue" --include="*.py"(check argument types)
---
Deprecated API Mapping
Methods Removed or Changed in v15
| Deprecated | Replacement |
|---|---|
frappe.db.sql_list() | frappe.db.get_all(..., pluck="name") |
frappe.db.sql_ddl() | Direct frappe.db.sql() with DDL |
frappe.get_module_path() (old sig) | frappe.get_module_path(module, ...) |
cur_page (JS) | frappe.router.current_route |
Methods Removed or Changed in v16
| Deprecated | Replacement |
|---|---|
doc_events controller override | extend_doctype_class |
override_doctype_class | extend_doctype_class |
frappe.utils.pdf.get_pdf() (old sig) | Updated PDF API |
frappe.get_hooks("boot_session") (old sig) | Updated boot hooks |
Migration Checklists
Pre-Migration Checklist
ALWAYS complete ALL items before starting any migration:
Infrastructure Requirements
v14 → v15
- [ ] Python >= 3.10 installed
- [ ] Node.js >= 16 installed
- [ ] MariaDB >= 10.6 installed
- [ ] Redis >= 6 installed
- [ ] pip packages updated:
bench pip install --upgrade pip setuptools - [ ] Disk space: minimum 2x database size free
v15 → v16
- [ ] Python >= 3.11 installed
- [ ] Node.js >= 18 installed
- [ ] MariaDB >= 10.6 installed
- [ ] Redis >= 7 installed
- [ ] pip packages updated:
bench pip install --upgrade pip setuptools - [ ] Disk space: minimum 2x database size free
Backup Verification
- [ ] Full database backup completed:
bench --site {site} backup - [ ] File backup completed:
bench --site {site} backup --with-files - [ ] Backup file verified (not corrupt): test restore on separate instance
- [ ] Backup stored in separate location (not on same server)
- [ ] Backup timestamp recorded in migration log
Code Freeze
- [ ] All custom app changes committed and pushed
- [ ] No in-progress features in custom apps
- [ ] All pull requests merged or deferred
- [ ] Git tags created for current version of each custom app
Communication
- [ ] Maintenance window scheduled with stakeholders
- [ ] Users notified of downtime
- [ ] Rollback plan documented and reviewed
Custom App Scan Checklist
For EACH custom app, complete this scan:
Python Code Scan
- [ ]
grep -rn "import" hooks.py— verify all imports resolve - [ ]
grep -rn "doc_events" hooks.py— check for method overrides - [ ]
grep -rn "scheduler_events" hooks.py— review timing - [ ]
grep -rn "frappe.enqueue" --include="*.py"— check job patterns - [ ]
grep -rn "frappe.db.sql" --include="*.py"— check raw SQL compatibility - [ ]
grep -rn "frappe.whitelist" --include="*.py"— verify decorators - [ ]
grep -rn "frappe.throw\|frappe.msgprint" --include="*.py"— check error handling
JavaScript Code Scan
- [ ]
grep -rn "cur_frm" --include="*.js"— deprecated, usefrm - [ ]
grep -rn "cur_page" --include="*.js"— deprecated in v15+ - [ ]
grep -rn "frappe.set_route" --include="*.js"— check signature - [ ]
grep -rn "frappe.call" --include="*.js"— verify async patterns - [ ]
grep -rn "frappe.db\." --include="*.js"— should not exist in Client Scripts
Configuration Scan
- [ ]
hooks.pysyntax is valid Python - [ ] All function paths in
hooks.pypoint to existing functions - [ ]
required_appslists all dependencies - [ ]
fixturesexport format is compatible - [ ]
patches.txtorpatches/directory structure is correct
Migration Execution Checklist
Phase 1: Staging Migration
- [ ] Staging environment created (separate from production)
- [ ] Production backup restored on staging
- [ ] Branch switched:
bench switch-to-branch version-{target} frappe erpnext - [ ] Custom apps updated to compatible branches
- [ ] Dependencies installed:
bench setup requirements - [ ] Migration executed:
bench --site {site} migrate - [ ] Assets rebuilt:
bench build - [ ] No errors in migration output
Phase 2: Staging Testing
- [ ] All DocTypes open without errors
- [ ] Create, read, update, delete operations work for key DocTypes
- [ ] All print formats render correctly (visual check)
- [ ] All workflows transition correctly
- [ ] All scheduled jobs execute (check scheduler.log)
- [ ] All custom reports generate without errors
- [ ] All API endpoints respond (test with curl/Postman)
- [ ] User permissions work correctly (test with different roles)
- [ ] File upload/download works
- [ ] Email sending works (test with test email)
- [ ] Page load time acceptable (< 3 seconds for main forms)
- [ ] Background jobs complete successfully
Phase 3: Production Migration
- [ ] Maintenance mode enabled:
bench --site {site} set-maintenance-mode on - [ ] Final backup taken (with files)
- [ ] All services stopped (workers, scheduler)
- [ ] Branch switched on production
- [ ]
bench setup requirementscompleted - [ ]
bench --site {site} migratecompleted without errors - [ ]
bench build --productioncompleted - [ ] Services restarted
- [ ] Maintenance mode disabled
- [ ] Quick smoke test passed (login, open key DocTypes)
Post-Migration Checklist
Immediate (First Hour)
- [ ] Login works for admin user
- [ ] Login works for regular users (test 2-3 different roles)
- [ ] Key business DocTypes open correctly
- [ ] No new entries in Error Log DocType
- [ ] Scheduler is running:
bench doctor - [ ] Workers are processing jobs
First Day
- [ ] All daily scheduled tasks executed
- [ ] No user-reported errors
- [ ] Email notifications sending correctly
- [ ] Print formats generating correctly
- [ ] API integrations working
- [ ] Performance baseline acceptable
First Week
- [ ] All weekly scheduled tasks executed
- [ ] Error Log reviewed — no recurring patterns
- [ ] User feedback collected
- [ ] Performance monitored — no degradation
- [ ] Backup schedule confirmed working on new version
Rollback Decision Checklist
Rollback IMMEDIATELY if ANY of these are true:
- [ ] Users cannot log in
- [ ] Key business processes are blocked (invoicing, ordering, etc.)
- [ ] Data corruption detected
- [ ] More than 3 CRITICAL errors in Error Log within first hour
- [ ] Performance degradation > 50% (page loads > 6 seconds)
- [ ] Scheduled jobs failing repeatedly
- [ ] External integrations broken with no quick fix
Rollback is NOT needed if:
- [ ] Only cosmetic issues (CSS, layout)
- [ ] Single non-critical report failing
- [ ] Warning messages (not errors) in logs
- [ ] Minor performance difference (< 20%)
Migration Workflow — Detailed Steps
Step 1: Identify Migration Path
Input Requirements
ALWAYS collect this information before starting:
1. Source version: Exact Frappe and ERPNext versions (bench version) 2. Target version: Desired Frappe and ERPNext versions 3. Custom apps: List all installed custom apps (bench --site {site} list-apps) 4. Environment: Development, staging, or production 5. Infrastructure: OS, Python, Node.js, MariaDB, Redis versions
Path Determination Rules
- NEVER skip major versions (v14 → v16 requires v14 → v15 → v16)
- ALWAYS migrate Frappe first, then ERPNext, then custom apps
- ALWAYS check if custom apps have version-specific branches
- For minor version jumps within same major (v15.20 → v15.30): direct upgrade is safe
Version Branch Mapping
| Version | Frappe Branch | ERPNext Branch |
|---|---|---|
| v14 | version-14 | version-14 |
| v15 | version-15 | version-15 |
| v16 | develop (or version-16) | develop (or version-16) |
Step 2: Check Breaking Changes
Process
For each version jump in the migration path:
1. Read the breaking changes table in SKILL.md for that version pair 2. Cross-reference with custom app functionality 3. Mark each breaking change as: AFFECTED / NOT AFFECTED / UNKNOWN 4. For UNKNOWN items: investigate further before proceeding
Priority Classification
| Priority | Description | Action Required |
|---|---|---|
| CRITICAL | Will cause immediate failure | Fix BEFORE migration |
| HIGH | Will cause errors in specific workflows | Fix BEFORE or DURING migration |
| MEDIUM | May cause issues under certain conditions | Fix DURING or AFTER migration |
| LOW | Cosmetic or non-blocking | Fix AFTER migration |
Step 3: Scan Custom Code
Automated Scan Process
For EACH custom app, run the deprecated pattern grep commands from SKILL.md:
APP_PATH="apps/{app_name}/{app_name}"
# Run all pattern checks and save results
echo "=== Scanning $APP_PATH ==="
# Count total issues
ISSUES=0
# Run each grep pattern from SKILL.md Step 3
# Collect results into a report fileManual Review Items
After automated scan, ALWAYS manually check:
1. hooks.py: Read completely, check all function paths exist 2. Custom DocType controllers: Verify lifecycle method compatibility 3. Custom reports: Check query syntax and API usage 4. Custom print formats: Verify Jinja template compatibility 5. Custom pages/workspace: Check frontend API usage 6. fixtures: Verify fixture export format is compatible
Step 4: Generate Migration Plan
Plan Customization Rules
Adapt the template from SKILL.md based on:
| Factor | Impact on Plan |
|---|---|
| Number of custom apps | More testing time needed per app |
| Data volume (>10GB) | Longer backup/restore, schedule accordingly |
| Active users (>100) | Longer maintenance window, more communication |
| Complex workflows | Dedicated workflow testing phase |
| External integrations | Integration testing phase |
| Multi-site setup | Per-site migration, staggered rollout |
Timing Estimates
| Activity | Small Site (<1GB) | Medium Site (1-10GB) | Large Site (>10GB) |
|---|---|---|---|
| Full backup | 5 min | 30 min | 2+ hours |
| Migration command | 10 min | 30 min | 1+ hours |
| Build assets | 5 min | 5 min | 10 min |
| Basic verification | 15 min | 30 min | 1 hour |
| Full test suite | 1 hour | 2 hours | 4+ hours |
Step 5: Generate Patch List
Patch Generation Rules
For each issue found in Step 3:
1. Identify the exact file and line number 2. Show the current (broken) code 3. Show the corrected code for the target version 4. Note if the fix is backward-compatible (works on source version too) 5. Prioritize: CRITICAL fixes first, then HIGH, MEDIUM, LOW
Backward-Compatible Fixes
ALWAYS prefer fixes that work on BOTH source and target versions:
# Backward-compatible: works on v14, v15, and v16
import frappe
if hasattr(frappe, 'new_api'):
frappe.new_api()
else:
frappe.old_api()Version-Conditional Code
When backward compatibility is impossible:
# hooks.py — version-conditional configuration
import frappe
frappe_version = int(frappe.__version__.split('.')[0])
if frappe_version >= 16:
extend_doctype_class = {
"Sales Invoice": "myapp.overrides.CustomSalesInvoice"
}
else:
doc_events = {
"Sales Invoice": {
"validate": "myapp.overrides.custom_validate"
}
}Rollback Procedures
When to Rollback
ALWAYS rollback if ANY of these conditions are met:
- Critical business processes are broken
- Data integrity issues detected
- Performance degradation > 50%
- More than 3 CRITICAL errors found post-migration
Rollback Steps
1. Immediate: Stop all services 2. Restore: Use the pre-migration backup (NEVER skip backup in Step 4) 3. Revert: Switch branches back to source version 4. Migrate: Run bench migrate on old version to ensure clean state 5. Verify: Run the same test checklist from Step 4 Phase 3 6. Communicate: Notify users of rollback and revised timeline
Post-Rollback Analysis
After rollback, ALWAYS:
1. Document what went wrong 2. Identify which breaking change was missed 3. Update the patch list with additional fixes 4. Re-test on staging before next attempt