# Vim Macro Recording Failed - Troubleshooting Macros That Don't Work
You recorded a macro to automate a tedious editing task, but when you play it back, something goes wrong. The cursor ends up in the wrong place, the wrong text gets deleted, or the macro simply does nothing. Macros are one of Vim's most powerful features, but they're also finicky. A single wrong keystroke during recording or a subtle assumption about cursor position can break everything.
Understanding Macro Basics
Macros in Vim are sequences of keystrokes stored in registers. You record to a register and play back from that register:
qa " Start recording to register 'a'
q " Stop recording
@a " Play macro once
@@ " Repeat last macro
10@a " Play macro 10 timesCheck what's stored in a register:
:register aOr see all registers:
:registersThis shows exactly what keystrokes are recorded. If your macro isn't working, this is the first place to look.
Common Recording Mistakes
Wrong Mode at Start
Macros should start in Normal mode unless you specifically need Insert mode. If you're in Insert mode when you start recording, the macro captures all mode switches:
" BAD: Starts in Insert mode
iHello World<Esc>qa...
" The macro includes 'iHello World<Esc>' at the beginningPress Esc to return to Normal mode before starting:
<Esc>qaRelative vs Absolute Movement
The most common macro failure is using relative movements that don't work the same way on replay:
" BAD: Uses relative movements
qa
2j " Move down 2 lines
dw " Delete word
qThis works on the first line, but after the macro runs, you're 2 lines down. Running it again moves another 2 lines down, deleting the wrong text.
Use searches or patterns instead:
" GOOD: Uses pattern-based movement
qa
/function<CR> " Find next function
dw " Delete word
qOr use 0 to go to the start of the line, $ for end of line, or ^ for first non-blank character.
Not Accounting for End of File
If your macro uses j to move down, it will fail when it reaches the end of the file:
qa
dd " Delete line
j " Move down (fails at EOF)
qBetter approaches:
qa
dd " Delete line
q " Don't move, let Vim handle line positioningOr use :delete instead of dd to avoid the position change.
Insert Mode Text Problems
When recording Insert mode text, be aware of what gets captured:
qa
iHello World<Esc>
qThis works, but if you make a typo and use backspace:
qa
iHello Woorld<BS><BS>rld<Esc>
qThe macro includes the typo and the corrections. It works, but it's cleaner to record it correctly.
For complex text insertion, consider using :normal or writing the text directly:
qa
I// <Esc> " Insert comment at line start
qDebugging Macros
Examine the Register Contents
Check exactly what's in your macro:
:echo @aThis shows the raw contents. Look for unexpected characters:
<80>sequences indicate special keys<Esc>should be a single escape character- Multiple
<Esc>sequences might cancel each other
Step Through Execution
Execute a macro in slow motion by putting it in the command line:
@aThen press : and use @: to repeat it, watching what happens.
Alternatively, split the macro into parts and execute each separately:
:let @a = "jdw" " First part: move down and delete word
@a
:let @a = "Aappended<Esc>" " Second part: append text
@aAbort on Error
By default, macros continue even when commands fail. Add ! to abort on error:
:normal! @aThis stops the macro when a command fails, making debugging easier.
Modifying Recorded Macros
You can edit a macro by modifying the register contents:
:let @a = "jdw3w" " Set macro to 'jdw3w'To append to a macro, use the uppercase register:
qA " Append to register 'a' (note: uppercase A)
... " Record more keystrokes
qThis adds to the existing macro in register 'a'.
Fixing Macros With Special Keys
If your macro includes special keys and you need to edit it, use the literal notation:
:let @a = "iHello\<CR>World\<Esc>"The \<key> notation represents special keys: \<CR>, \<Esc>, \<Tab>, \<Down>, etc.
Recursive Macros
Macros can call themselves, which is powerful but dangerous:
qa
dw
@a " Call itself recursively
qThis deletes a word and calls itself until it fails. But if you play it:
@aIt runs until it runs out of words to delete.
For safer recursion, use a count:
qa
dw
q
100@a " Run 100 times (or until it fails)Macro Execution Problems
Macro Does Nothing
If @a seems to do nothing:
- 1.Check if the register is empty:
:echo @a - 2.Check if you're in the right mode (should be Normal mode)
- 3.Check if the macro depends on specific conditions that aren't met
Macro Stops Mid-Execution
A macro might stop if:
- It encounters an error (like
jat the last line) - It switches to Insert mode and doesn't exit
- It triggers an interrupt (Ctrl+C)
Macro Affects Wrong Text
This usually means the macro assumes a cursor position that isn't true:
" Macro assumes cursor at start of line
0dw " But '0' is redundant if already at startOr uses relative positioning:
" BAD: Assumes specific column
10l " Move right 10 columnsBetter to search for patterns:
" GOOD: Find pattern and act
/ERROR<CR>
dwAdvanced Macro Techniques
Parameterized Macros
Use expression register for dynamic values:
qa
i= <C-r>=printf("%04d", line('.'))<CR><Esc>
qThis inserts = 0001, = 0002, etc. on each line.
Macro With Count
Pass a count to a macro:
3@a " Execute @a three timesInside the macro, you can use v:count:
:let @a = ":echo 'Count: ' . v:count\<CR>"Conditional Macro Logic
Use :normal with expression evaluation:
:let @a = ":if getline('.') =~ 'TODO'\<CR>:delete\<CR>:endif\<CR>"This deletes only lines containing "TODO".
Testing Macros Safely
Before running a macro on your entire file, test on a copy:
:sav! /tmp/testfile
" Run your macro here
" If something goes wrong, the original is safeOr use undo to revert:
u " Undo last change
:earlier 5m " Go back to state 5 minutes agoMacro Best Practices
- 1.Start from a known state: Press
Esctwice to ensure you're in Normal mode - 2.Use absolute positioning:
0,^,$, searches, noth,j,k,l - 3.Record in the middle of the file: Avoid edge cases at file start/end
- 4.Test incrementally: Record one step, test, record the next
- 5.Document complex macros: Keep a note of what each macro does
Example of a well-designed macro:
qa " Start recording to register 'a'
0 " Go to start of line
wiinserted <Esc> " Move to first word, insert text
/search<CR> " Find next occurrence
q " Stop recordingThis macro is robust because it:
- Starts with 0 to ensure a known position
- Uses w for word-based movement
- Uses search for absolute positioning
- Ends with search to find the next target
Macros are incredibly powerful once you understand their quirks. The key is to record from a known state, use absolute positioning instead of relative movements, and always verify with :registers what your macro actually contains.