Hey emacs-devel, The Emacs server doesn't print backtraces, so I'm trying to get these backtraces myself and return them to the server. After some exploration, I found about the debugger variable, and realized that I could actually force code to break into the debugger regardless of handlers using debug-on-signal. So far so good. Then I wrote the following "debugger" (defun my-handle-error (&rest args) (let (;; Prevent recursive error catching (debugger #'debug) (debug-on-quit nil) (debug-on-error nil) (debug-on-signal nil)) (pcase args (`(exit ,retv) retv) (`(error ,error-args) (setq saved-backtrace (with-output-to-string (backtrace))) (signal (car error-args) (cdr error-args)))))) And then I called my code as follows: (let* (;; Make sure that we'll intercept all errors (debug-on-quit t) (debug-on-error t) (debug-on-signal t) (debug-ignored-errors nil) ;; Make sure debugger has room to execute (max-specpdl-size (+ 50 max-specpdl-size)) (max-lisp-eval-depth (+ 50 max-lisp-eval-depth)) ;; Register ourselves as the debugger (debugger #'my-handle-error)) (my code here)) This was in part inspired by similar code in allout-widgets.el (although I think that code never worked, since it calls signal with a non-list second argument). When running on an emacs server, though, this code doesn't work. That is, it works fine the first time, but not on further invocations; so I stepped through the code in GDB, and I understood that the issue was here: if ( /* Don't try to run the debugger with interrupts blocked. The editing loop would return anyway. */ ! input_blocked_p () && NILP (Vinhibit_debugger) /* Does user want to enter debugger for this kind of error? */ && (EQ (sig, Qquit) ? debug_on_quit : wants_debugger (Vdebug_on_error, conditions)) && ! skip_debugger (conditions, combined_data) /* RMS: What's this for? */ && when_entered_debugger < num_nonmacro_input_events) { call_debugger (list2 (Qerror, combined_data)); return 1; } (in maybe_call_debugger). The first time around the debugger is called, but not the second time, because the `when_entered_debugger < num_nonmacro_input_events` is false (on the first round it evaluates to -1 < 0, and on the second one to 0 < 0). This reason for this clause was explained when this code was written back in 1991: /* The value of num_nonmacro_input_events as of the last time we started to enter the debugger. If we decide to enter the debugger again when this is still equal to num_nonmacro_input_events, then we know that the debugger itself has an error, and we should just signal the error instead of entering an infinite loop of debugger invocations. */ static EMACS_INT when_entered_debugger; The problem is that I'm running this code using emacsclient --eval '(error "abc")', and so the num_nonmacro_input_events value never increases. I "fixed" it this way: (defun my-handle-error (&rest args) (let (;; Prevent recursive error catching (debugger #'debug) (debug-on-quit nil) (debug-on-error nil) (debug-on-signal nil)) ;; HACK HACK HACK HACK HACK HACK HACK HACK HACK HACK HACK HACK ;; (setq num-nonmacro-input-events (1+ num-nonmacro-input-events)) ;; HACK HACK HACK HACK HACK HACK HACK HACK HACK HACK HACK HACK ;; (pcase args (`(exit ,retv) retv) (`(error ,error-args) (setq saved-backtrace (with-output-to-string (backtrace))) (signal (car error-args) (cdr error-args)))))) Is this going to have horrible consequences? If it is, could someone more experienced point me to how I am supposed to capture a backtrace and then rethrow an error? I can provide a full example if anyone wants to experiment and finds this description incomplete. Cheers, Clément.