Error when opening an Org File Containing an Emacs Table
Error
When I open an Org file containing an Emacs built-in table in Emacs:
* Tables
+-----+-----+-------+
| foo | bar | hello |
+-----+-----+-------+
| | | |
+-----+-----+-------+
| | | |
+-----+-----+-------+The error File mode specification error: (user-error Not at a table) is shown. I tried enabling toggle-debug-on-error but the backtrace isn’t shown. So I don’t know exactly what causes the error.
Debug
The reason toggle-debug-on-error (which sets debug-on-error to t) is failing you here comes down to two specific Emacs design choices:
- The
user-errorbypass: Emacs treats auser-errordifferently than a standard error. Auser-erroris explicitly designed to tell the user they did something wrong (like pressing a command in the wrong context) without popping up the debugger, so it inherently ignores debug-on-error. - The
normal-modesafety net: When Emacs opens a file, it runs all the initialization functions and hooks inside a condition-case. If a hook crashes, Emacs catches the error, wraps it in that “File mode specification error” message you saw, and forces the buffer to open anyway so you aren’t locked out of your file.
To find out exactly what Spacemacs package or hook is causing this, we have to bypass both of those safety nets.
How to Force the Backtrace
The cleanest and most surgical way to catch this is by trapping the specific error message itself before Emacs can suppress the debugger.
- Open Emacs (before opening the problematic Org file).
- Press
M-:(eval-expression). -
Evaluate this exact expression to tell the debugger to trigger the millisecond it sees that specific string:
(setq debug-on-message "Not at a table") - Now, open your problematic Org file.
However, this debug-on-message trick may not show the exact function that causes the error because it caught the error at the exact moment Emacs printed the message to your echo area. Because of how normal-mode handles file initialization, it wraps all major-mode hooks in a protective condition-case.
By the time the message function was called, Emacs had already suppressed the original crash, unwound the call stack, and returned to normal-mode. That’s why the backtrace doesn’t show any Org mode functions at all!
To find out exactly what is causing the crash, we need to catch the error before the stack unwinds. Since Emacs ignores debug-on-error for user-error types, we can forcefully inject the debugger directly into the user-error function using an advice.
The Surgical Trap
-
Turn off the old trap first:
(setq debug-on-message nil) -
Evaluate this block of Elisp. This temporarily modifies user-error so that if it specifically sees the string “Not at a table”, it immediately pauses execution and opens the debugger right at the source:
(defun my-catch-table-error (format-string &rest args) (when (string-equal format-string "Not at a table") (debug))) (advice-add 'user-error :before #'my-catch-table-error) - Open your problematic file again.
This time, the backtrace will be much longer and will contain the exact Org or Spacemacs function (likely a hook, a linter, or a minor mode like valign or toc-org) that is scanning your text and choking on the source block.
(Once you have the backtrace, you can remove the trap by evaluating (advice-remove 'user-error #'my-catch-table-error)).
Debugger entered: nil
(progn (debug))
(if (string-equal format-string "Not at a table") (progn (debug)))
my-catch-table-error("Not at a table")
apply(my-catch-table-error "Not at a table")
user-error("Not at a table")
org-table-shrink()
org-table-map-tables(org-table-shrink t)
org-mode()
set-auto-mode-0(org-mode nil)
set-auto-mode--apply-alist((("\\.epub\\'" . nov-mode) ...
set-auto-mode()
normal-mode(t)
after-find-file(nil t)
...Fix
Why it happens
Your configuration has the variable org-startup-shrink-all-tables set to t (or the file has a #+STARTUP: shrink keyword).
When the file loads, org-mode aggressively scans the buffer using a basic regex to find tables to shrink. It sees the | characters in your source block, assumes it is a native Org table, and blindly passes it to org-table-shrink.
However, org-table-shrink uses a stricter parser. It sees the +------+ rows, realizes it’s a table.el table rather than a standard Org table, and immediately throws the Not at a table error, crashing the initialization sequence.
You can replicate the same error by opening of an Org file with the following contents using vanilla Emacs:
#+STARTUP: shrink
* Tables
+-----+-----+-------+
| foo | bar | hello |
+-----+-----+-------+
| | | |
+-----+-----+-------+
| | | |
+-----+-----+-------+How to fix it
We can make org-table-shrink ignore tables provided by table.el:
(defun advice-org-table-shrink-ignore-table-el (orig-fn &rest args)
(unless (org-at-table.el-p)
(apply orig-fn args)))
(advice-add 'org-table-shrink :around #'advice-org-table-shrink-ignore-table-el)
Comments