Introduction
Welcome to the final module of our course, where we'll focus on the essential skills of debugging your code and packaging it into a shareable extension. In our previous lesson, you successfully created focus-writer-mode, a practical tool that bundles together multiple functions, a keymap, and a mode-line indicator. This is a fantastic achievement and a core practice in extending Emacs.
As you build more sophisticated tools like this, you'll inevitably encounter situations where things don't work as expected. This is a natural and universal part of programming. The key is not to avoid errors, but to learn how to understand and fix them.
This lesson tackles the first and most crucial step in that process: learning to read and interpret common Elisp error messages. Think of error messages not as failures, but as signposts. They are communications from the Emacs Lisp interpreter, telling you precisely what went wrong and often hinting at how to fix it. Our goal is to learn their language.
1. Anatomy of an Error: When Things Go Wrong
Let's begin by intentionally causing an error to see what it looks like. Go to your *scratch* buffer, type the following S-expression, place your cursor after the final parenthesis, and evaluate it with C-x C-e.
(this is not a valid function)
In the echo area at the bottom of your screen, you'll see a message that looks something like this:
Lisp error: (void-function this)
This message, though brief, is packed with information. It follows a common pattern for Elisp errors: it tells you the type of error and the offending symbol or value.
- Error Type:
void-function. This tells you the Lisp interpreter was expecting a function but found... nothing. The term "void" here means empty or undefined. - Offending Symbol:
this. This tells you which specific symbol caused the problem. The interpreter looked atthis, the first element of the list, expected it to be a defined function, and found it wasn't.
This fundamental structure applies to most errors you will encounter. To dive deeper into interpreting these "signposts," the following reading is an excellent starting point.
Programming in Emacs Lisp - List Processing
The classic 'Programming in Emacs Lisp' guide offers a gentle introduction to intentionally generating and understanding your first error message.
Read the section titled 'Generate an Error Message'. Focus on how the text breaks down the 'Symbol's function definition is void' message. The analogy of error messages as 'signposts' is a valuable mindset to adopt.
2. A Field Guide to Common Elisp Errors
Now that you understand the basic anatomy of an error message, let's explore a few of the most common types you'll encounter. For each one, we'll look at what causes it and how to interpret the message. The article "How to read Emacs Lisp" provides a great, practical overview of these.
a) void-function
As we just saw, this means you've tried to call a function that hasn't been defined.
- Common Causes: A simple typo in the function name, or forgetting to load a library that provides the function (e.g., with
require). - Example:
(mesage "A typo in the function name") ; 'mesage' instead of 'message'
b) void-variable
This is the sibling to void-function. It occurs when you try to get the value of a variable that has not been defined or assigned a value.
- Common Causes: A typo in a variable name, or trying to access a variable before it has been initialized (e.g., with
setqor inside aletblock). - Example:
This will produce an error like(message "My favorite number is %d" my-fav-num) ; my-fav-num is not definedLisp error: (void-variable my-fav-num).
c) wrong-type-argument
This error happens when you pass a value of an incorrect data type to a function. For example, passing a string to a function that expects a number.
- Common Causes: Passing arguments in the wrong order, or misunderstanding what type of data a function needs.
- Example:
This might produce an error like(+ 10 "apples") ; The '+' function only works on numbersLisp error: (wrong-type-argument number-or-marker-p "apples"). The message helpfully tells you it was expecting anumber-or-marker-p(a number or something that acts like one) but it got the string"apples".
To see detailed explanations of these errors, let's turn back to our guide.
Programming in Emacs Lisp - List Processing
This reading explores the 'void-variable' and 'wrong-type-argument' errors with clear examples.
Read the subsections 'Error Message for a Symbol Without a Value' and 'Using the Wrong Type Object as an Argument'. Pay attention to how the error messages clearly distinguish between a missing function and a missing variable value, and how they report the expected vs. actual data types.
d) Syntax Errors: Unbalanced parentheses, Invalid read syntax
These errors are different because they occur before Elisp even tries to evaluate your code. The Lisp reader (the part of the interpreter that parses text into data structures) fails because the text isn't a valid S-expression.
- Common Causes: A missing or extra parenthesis
(), or a stray quote". - Example:
Evaluating this will result in an(message "Hello, world!"Unbalanced parentheseserror in the echo area. Emacs is quite good at helping you find these. You can use the commandM-x check-parensor simply look for the visual indicators your editor provides for mismatched parentheses.
This next article offers a quick, practical reference for these errors and more.
How to read Emacs Lisp so that you can customize Emacs
The 'How to read Emacs Lisp' guide provides a concise cheat-sheet for common errors you'll hit when editing your configuration.
Skim through the sections: 'Scan error: "Unbalanced parentheses"', 'Cannot open load file', 'Lisp error: (void-function ...)', and 'Symbol's value as variable is void: _'. This will reinforce what we've learned and introduce the 'Cannot open load file' error, which is common when managing an Emacs configuration.
3. The Backtrace: Getting the Full Story
The echo area is fine for simple, one-line errors. But what happens when an error occurs deep inside a chain of function calls? The echo area message alone won't tell you how you got there. For that, we need a backtrace (also known as a stack trace).
A backtrace is a report that shows the sequence of function calls that led to an error, from the most recent call at the top to the initial command at the bottom.
To see this in action, you need to enable Emacs's built-in debugger. The easiest way is to run the command M-x toggle-debug-on-error.
Once enabled, any Lisp error will automatically pause execution and open a new buffer named *Backtrace* containing the full report.
Let's trigger one.
- Run
M-x toggle-debug-on-error. The echo area will confirmDebugger-on-error mode enabled. - Now, evaluate this code in your
*scratch*buffer. It defines a function that attempts to divide by zero, a classic arithmetic error.(defun cause-an-error () "A function designed to fail." (/ 100 0)) (cause-an-error)
You will be taken to a *Backtrace* buffer.

The video below gives a great visual walkthrough of enabling the debugger and reading the backtrace.
Learning To Use the Emacs Debugger - System Crafters Live!
David Wilson from System Crafters demonstrates how to enable the debugger and interpret the backtrace for an arithmetic error, similar to the one we just caused.
Watch from 18:53 to 22:46. Focus on understanding these key points: How to use M-x toggle-debug-on-error. What a backtrace (or stack trace) represents: the chain of function calls. How to read the backtrace from bottom to top to understand the flow of execution.
When you're finished exploring a backtrace, you can close the *Backtrace* buffer by pressing q. Remember to run M-x toggle-debug-on-error again to disable it when you're done debugging, otherwise Emacs will enter the debugger for every minor error.
Conclusion
Congratulations on taking your first steps into the world of debugging! Learning to read the signals Emacs sends you is a superpower. It transforms errors from frustrating roadblocks into helpful clues on your journey to mastering Elisp.
Key Takeaways:
- Elisp error messages are structured to be helpful, typically telling you the error type and the offending item.
- Common error types include
void-function,void-variable,wrong-type-argument, and syntax errors likeunbalanced-parentheses. - The
M-x toggle-debug-on-errorcommand is your entry point to serious debugging. It automatically provides a*Backtrace*buffer when an error occurs. - A backtrace is a list of function calls that shows the exact path of execution leading to the error, providing critical context for finding the bug's source.
Preview of the Next Lesson
Reading errors after they happen is a reactive approach to debugging. In our next lesson, we will learn a simple but powerful proactive technique. You'll learn to use the message function to print debugging information to the *Messages* buffer. This allows you to inspect the state of your program and the values of your variables as the code is running, helping you catch logical errors before they even cause a crash.