How to debug issues

When issues arise (and this is Emacs, they will), it pays to know how to use the diagnostic tools that are available to you.

The *Messages* buffer

Emacs may occasionally display a message in the echo area (the minibuffer at the bottom of the Emacs frame):


Emacs keeps a log of these messages in a hidden buffer named *Messages*. When you encounter an issue, it is a good idea to visit this buffer and search for warnings and error messages—or any suspicious activity surrounding the problematic event. With luck, it may offer some clues as to where you should look next.

The *Messages* buffer can be accessed with either:

  • M-x view-echo-area-messages
  • M-x switch-to-buffer RET *Messages*.
  • C-he
  • SPChe (for evil users)

If you find an error message, see dealing with errors below.

Dealing with errors

Emacs produces errors that can be cryptic for the uninitiated. Learning to interpret and debug them takes practice. Our guide on common errors and how to deal with them may help for the general cases, but failing that, your next step should always be to produce a backtrace from the error(s) and study them.

Once you have a backtrace, investigate the functions themselves using the tips for inspecting source code below.

Looking up documentation

Emacs is a self-documenting editor. Documentation is embedded into its source, and Emacs provides tools not only to look it up, but to inspect Emacs’ state at any time. One way to do this is with it’s describe-* family of commands.

:pushpin: Doom replaces the describe-* family with helpful.el. We’ll be using those instead.

For example:

  • M-x helpful-function RET add-hook — show documentation for the add-hook function, including usage examples, its definition, how it’s advised (if at all), and then some.
  • M-x helpful-variable — do the same, but with variables. Use it to inspect variables or change their values.
  • M-x helpful-key — this will tell you what’s bound to any arbitrary key sequence, including their documentation.
  • M-x doom/help-custom-variable — like helpful-variable but lists only variables that Emacs and packages intend for you to customize (it will omit private/internal variables).

Doom users will find these commands under SPCh—for evil users—and C-h for everyone else.

Searching Doom’s documentation

On top of Emacs documentation, Doom comes with its own manual (and of course, a library of tutorials and guides on our Discourse). There are commands for accessing and searching Doom’s manual from within Emacs:

  • M-x doom/help-search – Search all text in the manual.
  • M-x doom/help-search-headings – Search only headlines in our manual.

Profiling and benchmarking

Sometimes, Emacs can be slow, but if you can zero in on what’s responsible, perhaps it can be addressed. To do so, Emacs has a built-in profiler that can be toggled via M-x doom/toggle-profiler. Invoke it once to start it, and again to produce a report.

:pushpin: Additionally, explain-pause-mode may be used to profile running tasks or functions in emacs, similar to the unix program top that profiles running processes. Once activated, this minor-mode displays an auto-updating tabular buffer of running functions that updates every second. See GitHub - lastquestion/explain-pause-mode: top, but for Emacs. for more information about how to use this minor mode.

Evaluating elisp on-the-fly

Save yourself the trouble of a restart and evaluate elisp code on the spot with one of the following commands:

  • gr (+eval:region) — an evil operator that evaluates the selected or indicated region of code and display the return value in a popup overlay or buffer.
  • gR (+eval/buffer) — evaluate the whole buffer.
  • C-ce (+eval/buffer-or-region) — evaluate the whole buffer or selected region.

Or evaluate elisp directly in the ielm REPL:

  • SPCor (+eval/open-repl-other-window) — open a REPL for the current language.
  • C-cor (+eval/open-repl-other-window) — open a REPL for the current language.

:warning: Changes to ~/.doom.d/packages.el or your doom! block in ~/.doom.d/init.el require a restart (and doom sync) to take effect.

Testing elisp/packages in vanilla Emacs

Bisecting your private config

So something broke your config and you’re observing odd behavior or inscrutable error messages. All other options have been exhausted—what do?

Try bisecting your config, or the responsible Doom modules, one of two ways:

  1. Walk through the git history of your private config or Doom Emacs with git bisect.

  2. Or with comments:

    This step is as simple as it sounds: you comment out half of your config in $DOOMDIR/config.el, restart Emacs, and try to reproduce your issue. Rinse and repeat until you’ve isolated the problematic lines. Better yet, drill deeper into those lines and try bisecting those functions, and so on.

    :warning: Some folks stop bisecting at toggling modules in $DOOMDIR/init.el, but this is rarely helpful. It’s better to open the module’s config.el with SPCfe modules/some/module/config.el and bisect the module’s innards instead.

    Remember to consult a backtrace, if you can get one! The more you narrow it down before you bisect, the less bisecting work you’ll have to do!

Inspecting source code

Sometimes your best bet is to look at the source. While the helpful-* commands above will display documentation for functions and variables, you can use the following commands to jump directly to them:

  • M-x find-library – to jump to an installed package’s source.
  • M-x find-function – to jump to a function’s definition.
  • M-x find-variable – to jump to a variable’s origin.

:pushpin: Evil users can press gd (and for non-evil users: C-ccd) to jump to the definition of the function or variable under your cursor.

Otherwise, you can preform a text search of all loaded packages with one of:

  • M-x doom/help-search-load-path – perform a text search on all packages in load-path.
  • M-x doom/help-search-loaded-files – perform a text search on all currently-loaded *.el files.

Another option is to jump directly to a file Doom Emacs’ source code:

  • M-x +default/find-in-emacsd – jump to a file in Doom’s source (in ~/.emacs.d)
  • M-x +default/browse-emacsd – browse Doom’s source (in ~/.emacs.d)