Subject: Re: bug#76787: 31.0.50; Double backtrace in batch mode

From: Stefan Monnier <[email-masked]>
Date: Thu, 06 Mar 2025 15:26:40 -0500

> I think I'm in part to blame for this one.  It seems that one of them
> comes from the "normal" debugger and the other from
> `debug-early--handler`.

Rather than try and figure out how to coordinate the two places so they
don't both call a debugger, I generalized the
`debugger--last-error` mechanism with the patch below.

        Stefan

diff --git a/lisp/emacs-lisp/debug-early.el b/lisp/emacs-lisp/debug-early.el
index 48b71e7f9f0..e63edb19328 100644
--- a/lisp/emacs-lisp/debug-early.el
+++ b/lisp/emacs-lisp/debug-early.el
@@ -36,6 +36,8 @@
 ;; For bootstrap reasons, we cannot use any macros here since they're
 ;; not defined yet.
 
+(defvar debugger--last-error nil)
+
 (defalias 'debug-early-backtrace
   #'(lambda (&optional base)
       "Print a trace of Lisp function calls currently active.
@@ -76,15 +78,19 @@ 'debug-early-backtrace
 	                      (setq args (cdr args)))
 	               (princ " ")))
 	         (princ ")\n"))))
-	 base))))
+	 base))
+      (message "debug-early-backtrace...done")))
 
 (defalias 'debug--early
   #'(lambda (error base)
-  (princ "\nError: ")
-  (prin1 (car error))	; The error symbol.
-  (princ " ")
-  (prin1 (cdr error))	; The error data.
-  (debug-early-backtrace base)))
+      (if (eq error debugger--last-error) nil
+        (setq debugger--last-error nil)
+        (princ "\nError: ")
+        (prin1 (car error))             ; The error symbol.
+        (princ " ")
+        (prin1 (cdr error))             ; The error data.
+        (prog1 (debug-early-backtrace base)
+          (setq debugger--last-error error)))))
 
 (defalias 'debug-early                  ;Called from C.
   #'(lambda (&rest args)
diff --git a/lisp/emacs-lisp/debug.el b/lisp/emacs-lisp/debug.el
index f8af6eafa32..c1aaa1ac623 100644
--- a/lisp/emacs-lisp/debug.el
+++ b/lisp/emacs-lisp/debug.el
@@ -153,8 +153,6 @@ debugger--restore-buffer-state
     (insert (debugger--buffer-state-content state)))
   (goto-char (debugger--buffer-state-pos state)))
 
-(defvar debugger--last-error nil)
-
 (defun debugger--duplicate-p (args)
   (pcase args
     (`(error ,err . ,_) (and (consp err) (eq err debugger--last-error)))))