Skip to content

How to Debug Odoo: Complete Guide

DeployMonkey Team · March 11, 2026 9 min read

Debugging Odoo efficiently requires knowing which tool to reach for at each layer: Python exceptions, slow database queries, frontend JavaScript errors, and misconfigured records all need different approaches. This guide covers the full stack.

Layer 1 — Log Levels and Log Configuration

Odoo writes logs to stdout (or a file if configured). The log level controls verbosity:

# In odoo.conf
log_level = debug         # debug | info | warn | error | critical
log_db = True             # also write logs to ir.logging table in the DB
log_db_level = warning    # minimum level to write to DB

For targeted logging without flooding output, use --log-handler:

# Only debug logs for your module, info for everything else
odoo-bin -c odoo.conf --log-handler=my_module:DEBUG --log-level=info

# Debug SQL queries
odoo-bin -c odoo.conf --log-handler=odoo.sql_db:DEBUG

Inside your Python code, use the standard Python logging module:

import logging
_logger = logging.getLogger(__name__)

class MyModel(models.Model):
_name = 'my.model'

def my_method(self):
    _logger.debug('Entering my_method with ids: %s', self.ids)
    _logger.info('Processing %d records', len(self))
    _logger.warning('Unexpected state: %s', self.state)
    _logger.error('Failed to process record %d', self.id)

Layer 2 — pdb and ipdb Breakpoints

Python's built-in debugger (pdb) and the enhanced ipdb let you pause execution and inspect state:

# Install ipdb in your virtual environment
pip install ipdb

# In your model code
def problematic_method(self):
import ipdb; ipdb.set_trace()  # execution pauses here
result = self._compute_something()
return result

When execution hits the breakpoint, you get an interactive prompt in the terminal running Odoo:

(ipdb) self          # print the recordset
(ipdb) self.name     # inspect a field
(ipdb) n             # next line
(ipdb) s             # step into a function call
(ipdb) c             # continue execution
(ipdb) p self.env.user.name  # print expression
(ipdb) l             # list surrounding source code

Important: Only use breakpoints with --workers=0 (single-process mode). Multi-worker mode causes the breakpoint to block a worker silently.

odoo-bin -c odoo.conf --workers=0

Layer 3 — Odoo Shell

The Odoo shell is an interactive Python REPL with a fully initialized Odoo environment — perfect for exploring data, testing ORM queries, and running one-off fixes without writing a module:

odoo-bin shell -d your_database_name

Inside the shell:

# env is pre-loaded
partners = env['res.partner'].search([('is_company', '=', True)], limit=5)
for p in partners:
print(p.name, p.email)

# Test a model method
order = env['sale.order'].browse(42)
order.action_confirm()
env.cr.commit()  # persist changes (or rollback with env.cr.rollback())

# Inspect a computed field
print(order._fields['amount_total'].compute)

# Check which rules apply to a record
env['ir.rule']._get_failing(order, 'read')

Changes in the shell are in a transaction — call env.cr.commit() to save or env.cr.rollback() to discard.

Layer 4 — Developer Mode in the Browser

Activate developer mode via Settings → Activate Developer Mode or by appending ?debug=1 to any URL. Developer mode unlocks:

  • Technical menu: Inspect and edit views, models, fields, actions, and access rules directly in the UI.
  • View metadata: Hover over any field to see its technical name.
  • RPC logging: Use ?debug=assets to also rebuild and serve unminified JavaScript.
  • Edit views in place: Click the bug icon on any view to see the combined view XML.

Layer 5 — Browser DevTools for Frontend Debugging

Odoo's frontend is a JavaScript SPA. Use browser DevTools (F12) to debug it:

  • Console tab: JavaScript errors and warnings. Look for Uncaught Error or RPC failures.
  • Network tab: Filter by /web/dataset/call_kw to see all ORM RPC calls. Inspect request payload (model, method, args) and response for errors.
  • Sources tab: With ?debug=assets, set breakpoints in unminified Odoo JS. Use Ctrl+P to search for a file by name.
  • Application tab: Check localStorage for cached session data and cookies.

A common pattern: an RPC call fails silently in the UI. Open Network, click the failing call_kw request, and the response JSON will contain the Python traceback under error.data.debug.

Layer 6 — Database Query Debugging with pg_stat_activity

When Odoo is slow or locks up, the issue is often at the database layer:

-- Connect to PostgreSQL
psql -d your_database

-- See currently running queries
SELECT pid, now() - pg_stat_activity.query_start AS duration,
   query, state
FROM pg_stat_activity
WHERE state != 'idle'
ORDER BY duration DESC;

-- Find blocking queries
SELECT blocked.pid, blocked.query, blocking.pid AS blocking_pid,
   blocking.query AS blocking_query
FROM pg_stat_activity blocked
JOIN pg_stat_activity blocking
  ON blocking.pid = ANY(pg_blocking_pids(blocked.pid))
WHERE cardinality(pg_blocking_pids(blocked.pid)) > 0;

-- Kill a stuck query (replace 1234 with actual pid)
SELECT pg_terminate_backend(1234);

For slow query analysis, enable log_min_duration_statement in postgresql.conf:

log_min_duration_statement = 1000  # log queries taking more than 1 second

Then use EXPLAIN ANALYZE on the slow query to identify missing indexes.

Debugging on DeployMonkey Instances

DeployMonkey makes production debugging safer:

  • Live log streaming: View real-time Odoo logs from the dashboard without SSH access.
  • Shell access: Pro and Business plans include a browser-based Odoo shell for live data inspection.
  • Log level control: Adjust log levels per-module from the Instance Settings panel without editing config files.
  • Database snapshots: Take a manual backup before running risky debug-driven data fixes.

Combine with the ORM cheat sheet for efficient shell-based debugging.

FAQ

Why does my pdb breakpoint hang without showing a prompt?

Odoo is running in multi-worker mode. The breakpoint fires in a worker process that is not attached to your terminal. Restart Odoo with --workers=0 to use a single process, then breakpoints work normally.

How do I see the full Python traceback for an Odoo error in the browser?

Open browser DevTools → Network tab. Find the failing RPC request to /web/dataset/call_kw. In the response JSON, look at error.data.debug — it contains the full server-side traceback including file names and line numbers.

How do I debug a cron job that fails silently?

Go to Technical → Automation → Scheduled Actions, open the failing cron, and check the Log Notes chatter. Alternatively, run the cron method manually in the Odoo shell and watch for exceptions: env['ir.cron'].browse(cron_id).method_direct_trigger().

What log level should I use in production?

Use warn in production to minimize disk I/O and log noise. Switch to info or debug temporarily when investigating a specific issue, then revert. Debug logging on a busy instance generates gigabytes of logs per hour.

How do I find which XML ID corresponds to a record in the UI?

With developer mode active, open the record's form view and look at the URL — it contains the record ID. Then query: env['ir.model.data'].search([('res_id', '=', record_id), ('model', '=', 'model.name')]) in the shell to find the XML ID.

Debug Confidently on a Stable Platform

DeployMonkey gives you the tools to debug production issues safely: live log streaming, shell access, and one-click database snapshots before risky operations. View plans or start free today.