Subject: bug#78712: 31.0.50; definition is void in file-notify

From: Michael Albinus <[email-masked]>
Date: Mon, 09 Jun 2025 13:47:53 +0200

Al Haji-Ali <[email-masked]> writes:

Hi,

> I got this.
>
> file-notify-handle-event (file-notify (61 (rename attrib delete) "[redacted-dir]/[redacted-filename]") file-notify--callback-kqueue)
> file-notify-callback 61 deleted "[redacted-dir]/[redacted-filename]" nil #s(file-notify--watch "[redacted-dir]" "[redacted-filename]" auto-revert-notify-handler) "[redacted-dir]/[redacted-filename]" "[redacted-dir]"
> file-notify-handle-event (file-notify (61 stopped "[redacted-dir]/[redacted-filename]") auto-revert-notify-handler) [2 times]
> file-notify-callback 61 attribute-changed "[redacted-dir]/[redacted-filename]" nil #s(file-notify--watch "[redacted-dir]" "[redacted-filename]" nil) "[redacted-dir]/[redacted-filename]" "[redacted-dir]"
> file-notify--call-handler: Symbol’s function definition is void: nil
>
> Note that while I tested my artificial code on 31.0.50, showing the error being thrown, the log above is reported from my daily Emacs 29.1.
> For various reasons I cannot update to the latest version for my daily Emacs and as I mentioned the error happens somewhat randomly, so my only real chance to catch it is in this emacsen. 

Well, I haven't seen an action list (rename attrib delete) yet, but it
seems to be legitimate use.

I suppose the appended patch should fix it. It is assembled on top of
Emacs 31, but it should also apply on Emacs 29. Do you have a chance to
test it?

Best regards, Michael.

diff --git a/lisp/filenotify.el b/lisp/filenotify.el
index 9acf7651df5..96c2c46d1df 100644
--- a/lisp/filenotify.el
+++ b/lisp/filenotify.el
@@ -233,16 +233,18 @@ file-notify--call-handler
          (and (stringp file1)
               (string-equal (file-notify--watch-filename watch)
                             (file-name-nondirectory file1))))
-    (when file-notify-debug
-      (message
-       "file-notify-callback %S %S %S %S %S %S %S"
-       desc action file file1 watch
-       (file-notify--watch-absolute-filename watch)
-       (file-notify--watch-directory watch)))
-    (funcall (file-notify--watch-callback watch)
-             (if file1
-                 (list desc action file file1)
-               (list desc action file)))))
+    ;; The callback could have removed in `file-notify--rm-descriptor'.
+    (when (file-notify--watch-callback watch)
+      (when file-notify-debug
+        (message
+         "file-notify-callback %S %S %S %S %S %S %S"
+         desc action file file1 watch
+         (file-notify--watch-absolute-filename watch)
+         (file-notify--watch-directory watch)))
+      (funcall (file-notify--watch-callback watch)
+               (if file1
+                   (list desc action file file1)
+                 (list desc action file))))))
 
 (defun file-notify--handle-event (desc actions file file1-or-cookie)
   "Handle an event returned from file notification.