Enable Dark Mode!
an-overview-of-debugging-workflows-in-odoo-19.jpg
By: Sayed Mahir Abdulla KK

An Overview of Debugging Workflows in Odoo 19

Technical Odoo 19 Odoo Enterprises Odoo Community

Odoo development involves debugging, which is an important part. A Python model, an OWL component, an RPC call, or a record rule that prevents actions can be the source of problems with Odoo 19. Additionally, Odoo 19 made enough internal changes to the HTTP layer, OWL design, and frontend bundling that some of the previous debugging techniques are no longer effective.

This blog discusses real debugging methods for Odoo 19, including backend faults, frontend rendering problems, ORM behavior, and access permissions, using time-saving tools and procedures rather than only theoretical ones.

1. Understand what Odoo 19 actually sends back:

Odoo continues to return HTTP 200 and embed the actual exception within the JSON response body for the majority of JSON-RPC application problems. That is intentional rather than a bug. The JSON-RPC error object, which is located inside the response body, contains the actual error. People are constantly caught off guard by this.

This is how an actual Odoo 19 error response appears:

{
 "jsonrpc": "2.0",
 "id": 1,
 "error": {
   "code": 200,
   "message": "Odoo Server Error",
   "data": {
     "name": "odoo.exceptions.ValidationError",
     "debug": "Traceback (most recent call last):\n ...",
     "message": "The field 'email' is required.",
     "arguments": ["The field 'email' is required."]
   }
 }
}

Note that there's no exception_type field here. That field existed in older versions but was removed during the HTTP refactor. If you're parsing it in your code, it'll silently return undefined. Use data.name instead — it's stable across versions.

Tip: Always check response.error?.data?.name in your client code. String-match against the exception class name rather than any code or type field.

2. Enable server-side debug logging:

Browser DevTools only shows you the response. To see what's happening inside Odoo, you need the server logs. In Odoo 19, add this to your config file:

[options]
log_level = debug
log_handler = :DEBUG

Or pass it at startup:

python odoo-bin --log-level=debug --log-handler=:DEBUG -c odoo.conf

For workflow-specific debugging, you want more targeted logging to avoid noise. Target your module directly:

--log-handler=odoo.addons.your_module:DEBUG

This keeps the logs readable when you have a large instance running multiple modules.

3. Use Python's debugger inside Odoo methods:

Sometimes logs aren't enough. Drop a breakpoint directly into your model method:

def action_confirm(self):
   import pdb; pdb.set_trace()
   # or in Python 3.7+
   breakpoint()
   return super().action_confirm()

Warning: Never leave breakpoints in production. If Odoo freezes unexpectedly in dev, check whether a pdb call is blocking the process — it won't show an error, it just hangs.

4. Intercept JSON-RPC calls from the frontend:

The call passes through /web/dataset/call_kw if your workflow is triggered by a button or an OWL component. Open DevTools > Network in the browser, search for those requests, and filter by XHR. Both the response and the payload are JSON that may be read.

You can temporarily modify the RPC service in your JS to report every outgoing RPC call while debugging:

In your part or service, momentarily:

import { useService } from "@web/core/utils/hooks";
setup() {
   this.rpc = useService("rpc");
   const originalRpc = this.rpc;
   this.rpc = async (...args) => {
       console.log("[RPC Call]", args);
       const result = await originalRpc(...args);
       console.log("[RPC Result]", result);
       return result;
   };
}

Remove this before committing. It's a debugging tool, not a logging strategy.

5. Handle workflow errors properly in custom modules:

If you're writing a custom workflow and want Odoo to surface errors cleanly to the UI, use the right exception classes. Odoo 19 maps them to the correct HTTP behavior:

from odoo.exceptions import UserError, ValidationError, AccessError
# For business logic errors (shows as a user-visible warning dialog)
raise UserError("You can't confirm an order without a customer.")
# For field validation failures
raise ValidationError("The delivery date cannot be in the past.")
# For permission issues
raise AccessError("You don't have rights to approve this record.")
# Record deleted mid-transaction
raise MissingError("Record missing.")

Don't use generic Python exceptions like ValueError or Exception — Odoo catches those too, but the client-side error handling is messier and the debug output is less useful.

6. The workflow state machine isn't always obvious:

Server actions, scheduled actions, and field-triggered automations are examples of Odoo's automated processes that operate within their own transaction context. The entire transaction rolls back if something goes wrong in the middle of the operation, although there isn't always a noticeable fault.

Examine the ir.logging table directly:

SELECT name, level, message, create_date
FROM ir_logging
WHERE level IN ('ERROR', 'WARNING')
ORDER BY create_date DESC
LIMIT 50;

This is often faster than tailing log files, especially when you don't have direct server access.

To read more about Overview of Debugging in Odoo 19, refer to our blog Overview of Debugging in Odoo 19.


Frequently Asked Questions

Why does Odoo return HTTP 200 even when there's an error?

Odoo uses HTTP to execute JSON-RPC, where the application layer (JSON-RPC) and the transport layer (HTTP) are independent issues. HTTP 200 does not indicate whether your business logic was successful; it simply indicates that the server received the request and responded. The actual error is located under the error key within the JSON body. Give up examining HTTP status codes. Instead, look at response.error.

The exception_type field is missing from Odoo 19 error responses. What happened?

When Odoo redesigned the HTTP layer in version 17, it was removed. It was previously added inside odoo/http.py's serialize_exception() function; however, it no longer functions in the same manner. Instead, use data.name. The complete exception class route, such as odoo.exceptions, is provided.ValidationError, and it hasn't altered between iterations.

My server action runs without errors, but nothing changes in the database. Why?

There is no error if the domain or condition is incorrect. The action discovers no matching records, runs well, and ends. From its point of view, nothing went wrong; thus, Odoo has no idea what went wrong. There will be absolutely no feedback. This is the most frequent explanation for why nothing changes. Odoo will roll back the transaction and display an error dialog to the user if a real exception occurs.

What's the difference between UserError and ValidationError in Odoo?

Both initiate a discourse. Intent makes a difference. UserError is for business logic; the user attempted to perform something that is now prohibited by the process. Data validation errors occur when a field value violates a constraint. The distinction is important for code clarity and how Odoo's constraint system handles them internally, even though Odoo's user interface treats them nearly identically. If you use the incorrect one, it still functions, but it will be more difficult to read later.

Can I add custom logging inside an automated action without installing a debug module?

Yes, and it's quite simple. Add _logger = logging and import logging. Put getLogger(__name__) at the beginning of your model file. Then, if necessary, use _logger.info(), _logger.warning(), or _logger.debug(). Debug calls won't leak into production unless you specifically set debug level because output is sent to the server logs and ir_logging and respects Odoo's log-level filtering.

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