Custom DocType (validate, before_submit, on_submit) Not Running Until Supervisor Restart

Title

Custom DocType Controller Hooks (validate, before_submit, on_submit) Not Running Until Supervisor Restart (Production / Gunicorn Cache Issue)


Problem Statement

I created a custom DocType “Budget Adjustment” in my custom app/module (Budget Management) on Frappe/ERPNext v15. The DocType is submittable and has a proper Python controller file:

apps/budget_management/budget_management/budget_management/doctype/budget_adjustment/budget_adjustment.py

Inside the controller I added standard lifecycle hooks such as:

  • validate()

  • before_submit()

  • on_submit()

  • on_cancel()

However, after editing the Python controller code, none of these hooks were executing when saving/submitting the document from the UI. Example:

def validate(self):
    frappe.throw("SERVER VALIDATE IS RUNNING")

Even when saving a draft document (docstatus = 0), the form saved successfully and the hook did not run.


What I Observed

  • Saving from UI calls:
    POST /api/method/frappe.desk.form.save.savedocs

  • The controller class was correctly detected in console:

from frappe.model.base_document import get_controller
print(get_controller("Budget Adjustment"))
# budget_management.budget_management.doctype.budget_adjustment.budget_adjustment.BudgetAdjustment

  • Whitelisted methods in the same controller file worked fine using frappe.call(), but the lifecycle hooks did not run.

Root Cause / Fix

The issue was caused by stale Python code in the running production workers (Gunicorn).
My code changes were not being loaded into the running processes.

After running:

sudo supervisorctl restart all
bench --site aogc clear-cache

the updated controller code started working immediately, and validate(), before_submit(), and on_submit() fired correctly.


Question to Community

In production deployments of Frappe v15:

  1. What is the recommended correct restart procedure after changing DocType controller Python code?

  2. Is bench restart always sufficient, or should supervisorctl restart all (or systemd service restart) always be used?

  3. Are there best practices to avoid confusion caused by stale worker processes when developing custom apps?

i’m pretty sure in production environments, it’s not supposed to have the code edited, then again, every changes on the python code does require a bench restart

this is different from a development setup when bench start will use a file watcher to watch changes and will automatically reload the web process on the fly.

if you want to , you can try to utilize the server script feature. but this is a per site feature.