---
title: "Document Event Hooks in Frappe"
space: "Wiki"
url: "https://support.aakvatech.com/wiki/document-event-hooks-in-frappe"
updated: "2026-07-22"
---

Document event hooks allow you to execute custom logic at specific points in the lifecycle of a DocType record. These hooks are tied to events such as creation, saving, submission, or deletion of a document.

---

### **Available Document Events**

1. **`before_insert`**  
   Triggered before a new document is inserted into the database.  
   **Use Case:**  
   - Validate fields or ensure mandatory fields are populated.  
   - Set default values.

   ```python
   {
       "Sales Invoice": {
           "before_insert": "custom_app.events.before_insert_sales_invoice"
       }
   }
   ```

   ```python
   def before_insert_sales_invoice(doc, method):
       if not doc.customer:
           frappe.throw("Customer is required before inserting a Sales Invoice.")
   ```

---

2. **`after_insert`**  
   Triggered after a document is inserted into the database.  
   **Use Case:**  
   - Create related documents or perform post-creation actions.  
   - Notify users about new records.

   ```python
   {
       "Sales Invoice": {
           "after_insert": "custom_app.events.after_insert_sales_invoice"
       }
   }
   ```

   ```python
   def after_insert_sales_invoice(doc, method):
       frappe.msgprint(f"Sales Invoice {doc.name} has been created!")
   ```

---

3. **`before_validate`**  
   Triggered before a document is validated.  
   **Use Case:**  
   - Apply custom validation logic.  
   - Modify fields before standard validation.

   ```python
   {
       "Sales Invoice": {
           "before_validate": "custom_app.events.before_validate_sales_invoice"
       }
   }
   ```

   ```python
   def before_validate_sales_invoice(doc, method):
       if doc.discount_amount > doc.total:
           frappe.throw("Discount cannot be greater than the total amount.")
   ```

---

4. **`validate`**  
   Triggered during the validation phase, after `before_validate`.  
   **Use Case:**  
   - Perform additional validation checks.  
   - Manipulate field values post-validation.

   ```python
   {
       "Sales Invoice": {
           "validate": "custom_app.events.validate_sales_invoice"
       }
   }
   ```

   ```python
   def validate_sales_invoice(doc, method):
       if not doc.items:
           frappe.throw("Sales Invoice must have at least one item.")
   ```

---

5. **`before_save`**  
   Triggered before a document is saved in the database.  
   **Use Case:**  
   - Apply last-minute changes before saving.  
   - Trigger calculations or custom field updates.

   ```python
   {
       "Sales Invoice": {
           "before_save": "custom_app.events.before_save_sales_invoice"
       }
   }
   ```

   ```python
   def before_save_sales_invoice(doc, method):
       doc.additional_notes = "Checked by Admin"
   ```

---

6. **`on_update`**  
   Triggered after a document is updated in the database.  
   **Use Case:**  
   - Perform actions when a document is modified.  
   - Notify users or trigger workflows.

   ```python
   {
       "Sales Invoice": {
           "on_update": "custom_app.events.on_update_sales_invoice"
       }
   }
   ```

   ```python
   def on_update_sales_invoice(doc, method):
       frappe.msgprint(f"Sales Invoice {doc.name} has been updated!")
   ```

---

7. **`on_submit`**  
   Triggered when a document is submitted.  
   **Use Case:**  
   - Trigger financial or stock entries.  
   - Send notifications or execute workflows.

   ```python
   {
       "Sales Invoice": {
           "on_submit": "custom_app.events.on_submit_sales_invoice"
       }
   }
   ```

   ```python
   def on_submit_sales_invoice(doc, method):
       frappe.msgprint(f"Sales Invoice {doc.name} has been submitted.")
   ```

---

8. **`before_cancel`**  
   Triggered before a document is canceled.  
   **Use Case:**  
   - Validate conditions before allowing cancellation.  
   - Prevent cancellation under specific circumstances.

   ```python
   {
       "Sales Invoice": {
           "before_cancel": "custom_app.events.before_cancel_sales_invoice"
       }
   }
   ```

   ```python
   def before_cancel_sales_invoice(doc, method):
       if doc.status == "Paid":
           frappe.throw("Paid invoices cannot be canceled.")
   ```

---

9. **`on_cancel`**  
   Triggered after a document is canceled.  
   **Use Case:**  
   - Perform cleanup tasks, like reversing linked transactions.  
   - Notify users about cancellations.

   ```python
   {
       "Sales Invoice": {
           "on_cancel": "custom_app.events.on_cancel_sales_invoice"
       }
   }
   ```

   ```python
   def on_cancel_sales_invoice(doc, method):
       frappe.msgprint(f"Sales Invoice {doc.name} has been canceled.")
   ```

---

10. **`on_trash`**  
    Triggered when a document is deleted.  
    **Use Case:**  
    - Handle cleanup tasks like deleting linked records.

    ```python
    {
        "Sales Invoice": {
            "on_trash": "custom_app.events.on_trash_sales_invoice"
        }
    }
    ```

    ```python
    def on_trash_sales_invoice(doc, method):
        frappe.msgprint(f"Sales Invoice {doc.name} has been deleted.")
    ```

---

11. **`before_update_after_submit`**  
    Triggered before modifying a submitted document.  
    **Use Case:**  
    - Validate changes made to submitted documents.

    ```python
    {
        "Sales Invoice": {
            "before_update_after_submit": "custom_app.events.before_update_after_submit_sales_invoice"
        }
    }
    ```

    ```python
    def before_update_after_submit_sales_invoice(doc, method):
        if doc.discount_amount > 1000:
            frappe.throw("Cannot give discounts higher than 1000 after submission.")
    ```

---

12. **`on_update_after_submit`**  
    Triggered after modifying a submitted document.  
    **Use Case:**  
    - Perform tasks like recalculating reports after modifications.

    ```python
    {
        "Sales Invoice": {
            "on_update_after_submit": "custom_app.events.on_update_after_submit_sales_invoice"
        }
    }
    ```

    ```python
    def on_update_after_submit_sales_invoice(doc, method):
        frappe.msgprint(f"Sales Invoice {doc.name} was updated post-submission.")
    ```

---

### **General Structure of a Document Event Hook**

```python
doc_events = {
    "DocTypeName": {
        "event_name": "path.to.method"
    }
}
```

---

### **Best Practices**
1. **Modularize Your Code:** Keep event handlers in separate files for clarity and maintainability.
2. **Optimize Performance:** Avoid heavy computations or long-running tasks in hooks to prevent delays.
3. **Error Handling:** Use `try` and `except` blocks to handle unexpected errors gracefully.
4. **Use Frappe APIs:** Leverage Frappe’s built-in APIs for operations like querying, updating, and notifying.
