3. Post-Live Issues and Fixes

3.1 Issues Found During V15 Staging (Caught Before Production)

Issue

Root Cause

Fix Applied

Custom Jinja filters not applying in print formats

jinja_filters hook key not renamed to jinja in hooks.py; v15 silently ignored old key

Renamed hook key in hooks.py for all affected custom apps

frappe.db.sql() throwing InterfaceError on custom reports

SQL queries used positional params without values tuple

Added explicit values tuples to all frappe.db.sql() calls

Notification on_login hook not firing

on_login deprecated in v15; replacement is on_session_creation

Updated hooks.py to use on_session_creation across all apps

bench build failing with ESM import errors

Node upgraded to 18 but old package-lock.json had Node 16 resolved paths

Deleted node_modules and package-lock.json, ran fresh npm install

Scheduled email digest not sending

Worker service names changed after bench setup supervisor re-run; old supervisor jobs still running

Ran sudo supervisorctl reread && update to load new worker definitions

3.2 Issues Found During V16 Staging (Caught Before Production)

Issue

Root Cause

Fix Applied

Desk blank white screen on login

Custom Vue 2 component with Options API syntax crashed Vue 3 runtime

Rewrote component using Vue 3 Composition API; rebuilt assets

All frappe.call() in 3 apps returning success but no data processed

Old callback-style frappe.call() not invoked in v16; no .then() fallback

Migrated all frappe.call() to Promise .then() chain pattern

frappe.enqueue() failing with serialisation error

Custom object passed as argument was not JSON-serialisable

Replaced custom object with its dict representation before enqueue

PDF generation broken for 2 print formats

frappe.boot.sysdefaults referenced in Jinja template; key removed in v16

Updated templates to use frappe.sys_defaults

bench migrate aborted on custom patch file

Patch used frappe.db.exists() result as doc name; v16 returns True/False

Patched migration file to use frappe.db.get_value() instead

Redis connection refused on bench start

Redis 7 rejected deprecated bind and save directives in old redis.conf

Cleaned redis.conf of deprecated directives; restarted Redis 7

3.3 Post Production Cutover Issues (V16 Live)

P1 — Critical (Resolved within 24 hours)

Issues that blocked core business operations.

Background jobs not processing after go-live: Supervisor worker service files from v15 were copied to production and were incompatible with v16 worker naming. Fix: ran bench setup supervisor --yes on production, reloaded supervisor.

Two custom apps still on v15-compat branch accidentally deployed to production: Caught within 30 minutes via error logs. Fix: git checkout v16-compat and bench build --app <app>.

P2 — High Priority (Resolved within 72 hours)

Issues that degraded functionality but had workarounds.

Scheduled jobs not triggering: Invalid cron expression in one app's hooks.py that passed v15 validation but failed v16's stricter cron parser. Fix: corrected cron string, ran bench update --patch.

Custom dashboard charts showing no data: frappe.db.count() filter format changed to dict-only in v16; one report used list-of-lists format. Fix: updated filter format in the report script.

File attachments not visible in custom portal: app_include path in hooks.py pointed to pre-Vite build path. Fix: updated path to /assets/<app>/dist/ format.

P3 — Medium (Resolved within 1 week)

Minor issues with low business impact.

Custom list view column formatters not applying: frappe.ui.form.on used for list view in v14/v15 style; v16 requires frappe.listview_settings[doctype] pattern. Fixed across 4 apps.

Email queue processing slower than v15: resolved by tuning worker concurrency in Procfile based on actual queue depth observed post-go-live.

frappe.utils.dateutils import errors in two older patch files: resolved by updating import to frappe.utils.date_utils.