If you are new to Emacs, you may run into some errors, especially after you copied some elisp snippets from the Internet or elsewhere. Don't panic! It happens, it's just part of the learning process. Even an experienced Emacs user could run into there issues from time to time.

But in order to ease the pain, I will introduce a bunch of Emacs built-in features to help you troubleshoot and eventually solve the problems by yourself in this post. Let's dive in!
Starting a Clean Emacs
When you have some problems/errors with built-in features, the first thing you may need to do is to run emacs -Q
to start another clean Emacs instance without any configurations from your emacs.d
.
Here is how to do it in details if you are not familiar with the terminal:
-
If you use Linux/macOS, open a terminal, then run the command
emacs -Q
.emacs -Q
on LinuxIf you prefer to use Emacs in a terminal or run Emacs on a server, you can append an argument
-nw
to the command, that is,emacs -Q -nw
.P.S. If you want to know more about the command line arguments, you can look it up in the
man
manual (typeman emacs
in the terminal) or typeemacs --help
to see the help information, so as to get a better understanding of how to run Emacs from the command line. -
Or if you use Windows, you can run the
cmd
program first (typeSuper+r cmd ENTER
),cd
into the Emacs bin directory, then typerunemacs.exe -Q
to run it.emacs -Q
on Windows cmd
Troubleshooting a Problematic Package
emacs -Q
helps to debug built-in features. But when it comes to debugging third-party packages, like the ones you install from melpa, we need to do a bit more, as we need to load the package.
There are roughly two ways to do that:
- Using the
package
machinery, - Loading directly from a specific directory.
Whichever you take, the goal here is to only load that specific package so that there is zero possibility that it's introduced by other packages.
Using the package
Machinery
For example, if we now have a problem with my ppcompile package, we can prepare a snippet (e.g. in /tmp/try-ppcompile.el
) to prepare the debugging environment:
;; you don't need this if you never change this variable
(setq package-user-dir "~/.emacs.local.d/elpa")
;; init the package manager
(require 'package)
(package-initialize)
;; load the problematic package
(require 'ppcompile)
Now open up a terminal/cmd, type emacs -Q -l /tmp/try-ppcompile.el
, and it will start a clean Emacs with ppcompile loaded. From there, we can investigate further to see the problem.
Loading Directly From a Specific Directory
There are times that you can't utilize the package machinery to load the package, for example, you git-clone a package and load it from your local file system directly. In that case, you can use Emacs' -L
argument to specify the directory and load the package.
For example, type emacs -Q -L /tmp/ppcompile/ --eval "(require 'ppcompile)"
to launch a new Emacs with the package and start debugging immediately.
Note that you can specify more than one directory with more -L
.
Using --debug-init
To Debug Start-up Errors
It's not uncommon that after you updated your emacs.d
, Emacs just errored out when you ran it again.

Don't panic! Look carefully, and you will notice that Emacs has already told you how to troubleshoot it. (Pay attention to the second red line in the above screenshot)
Open a terminal, type emacs --debug-init
, as Emacs tells us in the message, to start a new one. It will tell you where the error comes exactly from and the backtrace as well. Be patient and try to understand the problem, you will come up with a solution, hopefully! (The root cause in the screenshot is that the a-bug-function
function is not defined)

--debug-init
to run Emacs
Running M-x toggle-debug-on-error
to Enable Debugging
You may see something like the below when you're using Emacs:

To simulate such an error, for example, say we have a silly welcome
command as below:
(defun welcome ()
(interactive)
(this-func-not-exist))
Now when you type M-x welcome
to invoke the command, you will see the error as in the above screenshot.
Now, type M-x toggle-debug-on-error
to enable debugging (in case you don't know yet, here is how to type M-x toggle-debug-on-error
on the keyboard: ALT+x toggle-debug-on-error RETURN
), then it will bring up a new window with the backtrace when we hit M-x welcome
once again.

From the backtrace, we can see that the error is due to the function of this-func-not-exist
does not exist.
Setting the debug-on-message
Variable
Other times, you may see some unexpected message on the echo area at the bottom. You can try to play around the debug-on-message
variable to get the backtrace of where it comes from and figure it out.
For example, the below command will send out a message welcome who?
when you invoke it:
(defun welcome ()
(interactive)
(message "welcome who?"))
Let's pretend that we now want to find out who print the nonsense message of welcome who
, and we can utilize the debug-on-message
variable to set up a regular expression, for instance, (setq debug-on-message "welcome who")
.
Once there is a message that matches the regexp, Emacs will show the backtrace, and we will find out who is the culprit there:

Other Debugging Helpers and Facilities
Here are variable ways to look up help docs in Emacs:
C-h f
to look up a function(C-h f
means to typeCTRL+h f
in the keyboard)C-h v
to look up a variableC-h k
to look up a keybindingC-h m
to look up which major mode and minor modes are enabled in the current bufferC-h l
to view lossage, put it in another way, you will see the history of the invoked commands in a dedicated buffer
Last but not least, Emacs also has other machineries to help debug:
- Running
M-x describe-char
to see the properties of the character at point, for example, its font face. - Leveraging the
debug-on-entry
function. Emacs starts the debugger automatically when your function has an error, also refer to debug-on-entry (Programming in Emacs Lisp) - www.gnu.org. - Setting the
debug-on-quit
variable, please head over to debug-on-quit (Programming in Emacs Lisp) - www.gnu.org for details. - Specifying
--init-directory
. Emacs 29 adds a command line argument of--init-directory
to specify a directory other than~/.emacs.d/
to run Emacs, where we can put our debugging code to do the investigation separately.