Enable Dark Mode!
how-to-handle-scheduled-action-errors-in-odoo-19.jpg
By: Safa KB

How to Handle Scheduled Action Errors in Odoo 19

Technical Odoo 19 Odoo Enterprises Odoo Community

Scheduled Actions (ir.cron) execute server-side Python code at certain intervals of time. Any errors raised by scheduled actions are managed within Odoo 19 by a failure tracking mechanism in the ir_cron.py file. Learning about how the system works can help you make your cron jobs more reliable.

Cron Job Failure Handling Mechanism in Odoo 19

However, before we explain the methods, here’s what Odoo 19 does behind the scenes by default:

  • Every cron action has a failure_count and first_failure_date field on ir.cron
  • On each exception, the _callback() function does a rollback on the transaction and raises the exception again. The cron action status is updated to "failed".
  • If there are five consecutive failures over a span of seven days, then the cron action will be deactivated automatically, and the _notify_admin() function will be called to notify the administrator.
  • Any successful execution will reset the failure_count value to 0.
  • With this, it should be easy for you to handle cron actions with greater confidence.

Method 1: Try/Except in the Cron Code Body

The easiest way is to put your code in a try/except block. This allows you to catch certain exceptions and deal with them appropriately (log, notify, skip), all while preventing the job from failing completely.

from odoo import models, api
import logging
_logger = logging.getLogger(__name__)
class SaleOrder(models.Model):
   _inherit = 'sale.order'
   @api.model
   def action_sync_orders(self):
       orders = self.search([('state', '=', 'draft')])
       for order in orders:
           try:
               order._sync_to_external_system()
           except ConnectionError as e:
               _logger.warning(
                   "Sync failed for order %s: %s. Skipping.",
                   order.name, e
               )
               continue
           except Exception as e:
               _logger.error(
                   "Unexpected error for order %s: %s",
                   order.name, e, exc_info=True
               )
               raise  # re-raise to mark the job as failed

When to use this:

To ignore individual failures but avoid failing the whole task execution process.

To be able to discern recoverable from unrecoverable exceptions. Raising the exception again ensures the failure counter is updated by Odoo’s failure counting system.

Method 2: Override _notify_admin for Custom Alerts

Odoo 19 calls the method _notify_admin() of ir.cron when a task fails several times and gets deactivated. The default version only issues a log entry. Overriding this method will enable sending an email notification, posting a chat message, or invoking an external API URL endpoint.

from odoo import models
import logging
_logger = logging.getLogger(__name__)
class IrCron(models.Model):
   _inherit = 'ir.cron'
   def _notify_admin(self, message):
       mail_template = self.env.ref(
           'your_module.cron_failure_email_template',
           raise_if_not_found=False
       )
       if mail_template:
           # Use sudo() and pass no record_id (send a generic notification)
           # OR find the cron by matching its active=False state
           cron = self.env['ir.cron'].sudo().search(
               [('active', '=', False)], order='write_date desc', limit=1
           )
           if cron:
               mail_template.send_mail(cron.id, force_send=True)  # ? valid id
       # Always keep the default log
       super()._notify_admin(message)

Xml

<record id="cron_failure_email_template" model="mail.template">
   <field name="name">Cron Job Failure Alert</field>
   <field name="model_id" ref="base.model_ir_cron"/>
   <field name="subject">Scheduled Action Failed: {{ object.cron_name }}</field>
   <field name="body_html">
       &lt;p&gt;The scheduled action &lt;strong&gt;{{ object.cron_name }}&lt;/strong&gt;
       has been deactivated after repeated failures.
       Please check the server logs for details.&lt;/p&gt;
   </field>
   <field name="email_to">admin@yourcompany.com</field>
</record>

When to use this:

You need proactive alerts before someone notices the cron is off.

Your production system must notify a DevOps team, Slack channel, or support desk automatically.

Method 3: Check failure_count and first_failure_date for Conditional Logic

The Odoo 19 version contains the failure data within the field of the ir.cron model. These fields can be used within your cron function to adapt depending on the number of failures.

from odoo import models, api, fields
import logging
_logger = logging.getLogger(__name__)
class StockPicking(models.Model):
   _inherit = 'stock.picking'
  
   @api.model
   def action_retry_failed_pickings(self):
       cron = self.env['ir.cron'].sudo().search(
           [('code', 'like', 'action_retry_failed_pickings')], limit=1
       )
       if cron and cron.failure_count >= 3:
           _logger.warning(
               "Cron '%s' has failed %s times since %s. "
               "Switching to safe mode (read-only check only).",
               cron.cron_name,
               cron.failure_count,
               cron.first_failure_date,
           )
           # Safe mode: only report the problem, don't attempt writes
           failed = self.search([('state', '=', 'confirmed'), ('scheduled_date', '<', fields.Datetime.now())])
           _logger.warning("Found %s overdue pickings during safe mode run.", len(failed))
           return
       # Normal mode: attempt processing
       failed_pickings = self.search([
           ('state', '=', 'confirmed'),
           ('scheduled_date', '<', fields.Datetime.now()),
       ])
       for picking in failed_pickings:
           try:
               picking.action_assign()
           except Exception as e:
               _logger.error("Error assigning picking %s: %s", picking.name, e, exc_info=True)
               raise

When to use this:

Your task has negative consequences (writing, emailing, API requests) that you would like to avoid during a series of failures. You want a "safe mode" where diagnostics are collected without further damage. You need a custom escalation depending on how long your task has failed.

Odoo 19 comes with built-in failure logging for tasks, recovery logging when your tasks fail to recover, and deactivating tasks that keep failing. Using custom error handling, notifications to administrators, and failure-aware programming, you can turn scheduled actions into production-ready ones.

To read more about How to Configure Scheduled Actions in Odoo 19, refer to our blog How to Configure Scheduled Actions in Odoo 19.


Frequently Asked Questions

What happens when a scheduled task fails in Odoo 19?

If a cron task encounters an error, then Odoo rolls back the database transaction, marks the task as being failed, and increases the value of failure_count. In case of a continuous failure in five attempts on a weekly basis, Odoo automatically sets the task as being inactive and calls the method _notify_admin().

Is it recommended that I always try to handle exceptions within my cron tasks?

Not necessarily. You should catch exceptions when you are certain that recovery can be attempted. Otherwise, allow exceptions to propagate to the caller for further handling so that Odoo can manage the situation accordingly.

Is there a way for me to get notifications about the deactivation of my cron task?

You can do so by inheriting the model ir.cron and overriding the method _notify_admin(). With that, you could send an email notification, make a note on the chatter, open a ticket at your helpdesk, call your webhooks, and even integrate with monitoring services such as Slack and Microsoft Teams.

If you need any assistance in odoo, we are online, please chat with us.



0
Comments



Leave a comment



Recent Posts

whatsapp_icon
location

Calicut

Cybrosys Technologies Pvt. Ltd.
Neospace, Kinfra Techno Park
Kakkancherry, Calicut
Kerala, India - 673635

location

Kochi

Cybrosys Technologies Pvt. Ltd.
1st Floor, Thapasya Building,
Infopark, Kakkanad,
Kochi, India - 682030.

location

Bangalore

Cybrosys Techno Solutions
The Estate, 8th Floor,
Dickenson Road,
Bangalore, India - 560042

Send Us A Message