Subject: bug#72954: 31.0.50; Error when calling gnus-summary-move-article

From: Michael Heerdegen <[email-masked]>
Date: Mon, 02 Sep 2024 10:34:19 +0200

Hello,

I am browsing the result of a `gnus-group-read-ephemeral-search-group'
call.  Then I invoke `gnus-summary-move-article' (with point at the
article I want to move) and get this error:

Debugger entered--Lisp error: (wrong-type-argument number-or-marker-p nil)
  (range-compress-list (nil))
  (gnus-compress-sequence (nil))
  (#f(compiled-function (artgroup) #<bytecode -0x9608aa7701c677>) (nil nil))
  (mapcar #f(compiled-function (artgroup) #<bytecode -0x9608aa7701c677>) ((nil nil)))
  (#f(compiled-function (act) #<bytecode 0x1674e349f0e03dda>) ((2139) set nil))
  (mapcan #f(compiled-function (act) #<bytecode 0x1674e349f0e03dda>) (((2139) set nil) ((2139) del (unexist seen forward unsend download cache save score dormant bookmark killed expire reply tick))))
  (cl-mapcan #f(compiled-function (act) #<bytecode 0x1674e349f0e03dda>) (((2139) set nil) ((2139) del (unexist seen forward unsend download cache save score dormant bookmark killed expire reply tick))))
  (nnselect-request-set-mark "search->subject--bug--from---" (((2139) set nil) ((2139) del (unexist seen forward unsend download cache save score dormant bookmark killed expire reply tick))) "nnselect-ephemeral")
  (gnus-request-set-mark "nnselect:search->subject--bug--from---" (((2139) set nil) ((2139) del (unexist seen forward unsend download cache save score dormant bookmark killed expire reply tick))))
  (gnus-summary-push-marks-to-backend 2139)
  (#f(compiled-function (&optional n to-newsgroup select-method action) "Move the current article to a different newsgroup.\nIf N is a positive number, move the N next articles.\nIf N is a negative number, move the N previous articles.\nIf N is nil and any articles have been marked with the process mark,\nmove those articles instead.\nIf TO-NEWSGROUP is string, do not prompt for a newsgroup to move to.\nIf SELECT-METHOD is non-nil, do not move to a specific newsgroup, but\nre-spool using this method.\n\nWhen called interactively with TO-NEWSGROUP being nil, the value of\nthe variable `gnus-move-split-methods' is used for finding a default\nfor the target newsgroup.\n\nFor this function to work, both the current newsgroup and the\nnewsgroup that you want to move to have to support the `request-move'\nand `request-accept' functions.\n\nACTION can be either `move' (the default), `crosspost' or `copy'." (interactive "P") #<bytecode -0xa0099b9b29482be>) nil)
  (funcall #f(compiled-function (&optional n to-newsgroup select-method action) "Move the current article to a different newsgroup.\nIf N is a positive number, move the N next articles.\nIf N is a negative number, move the N previous articles.\nIf N is nil and any articles have been marked with the process mark,\nmove those articles instead.\nIf TO-NEWSGROUP is string, do not prompt for a newsgroup to move to.\nIf SELECT-METHOD is non-nil, do not move to a specific newsgroup, but\nre-spool using this method.\n\nWhen called interactively with TO-NEWSGROUP being nil, the value of\nthe variable `gnus-move-split-methods' is used for finding a default\nfor the target newsgroup.\n\nFor this function to work, both the current newsgroup and the\nnewsgroup that you want to move to have to support the `request-move'\nand `request-accept' functions.\n\nACTION can be either `move' (the default), `crosspost' or `copy'." (interactive "P") #<bytecode -0xa0099b9b29482be>) nil)
  (#f(lambda (f n _) [cl-struct-my-gnus-summary-process-marked-tags cl-struct-my-gnus-summary-pos-tags t] (funcall f n)) #f(compiled-function (&optional n to-newsgroup select-method action) "Move the current article to a different newsgroup.\nIf N is a positive number, move the N next articles.\nIf N is a negative number, move the N previous articles.\nIf N is nil and any articles have been marked with the process mark,\nmove those articles instead.\nIf TO-NEWSGROUP is string, do not prompt for a newsgroup to move to.\nIf SELECT-METHOD is non-nil, do not move to a specific newsgroup, but\nre-spool using this method.\n\nWhen called interactively with TO-NEWSGROUP being nil, the value of\nthe variable `gnus-move-split-methods' is used for finding a default\nfor the target newsgroup.\n\nFor this function to work, both the current newsgroup and the\nnewsgroup that you want to move to have to support the `request-move'\nand `request-accept' functions.\n\nACTION can be either `move' (the default), `crosspost' or `copy'." (interactive "P") #<bytecode -0xa0099b9b29482be>) nil (2139))
  (funcall #f(lambda (f n _) [cl-struct-my-gnus-summary-process-marked-tags cl-struct-my-gnus-summary-pos-tags t] (funcall f n)) #f(compiled-function (&optional n to-newsgroup select-method action) "Move the current article to a different newsgroup.\nIf N is a positive number, move the N next articles.\nIf N is a negative number, move the N previous articles.\nIf N is nil and any articles have been marked with the process mark,\nmove those articles instead.\nIf TO-NEWSGROUP is string, do not prompt for a newsgroup to move to.\nIf SELECT-METHOD is non-nil, do not move to a specific newsgroup, but\nre-spool using this method.\n\nWhen called interactively with TO-NEWSGROUP being nil, the value of\nthe variable `gnus-move-split-methods' is used for finding a default\nfor the target newsgroup.\n\nFor this function to work, both the current newsgroup and the\nnewsgroup that you want to move to have to support the `request-move'\nand `request-accept' functions.\n\nACTION can be either `move' (the default), `crosspost' or `copy'." (interactive "P") #<bytecode -0xa0099b9b29482be>) nil (2139))
  (progn (select-window (car save-selected-window--state) 'norecord) (set-window-fringes window 0 0) (funcall query f n articles))
  (unwind-protect (progn (select-window (car save-selected-window--state) 'norecord) (set-window-fringes window 0 0) (funcall query f n articles)) (internal--after-with-selected-window save-selected-window--state))
  (save-current-buffer (unwind-protect (progn (select-window (car save-selected-window--state) 'norecord) (set-window-fringes window 0 0) (funcall query f n articles)) (internal--after-with-selected-window save-selected-window--state)))
  (let ((save-selected-window--state (internal--before-with-selected-window window))) (save-current-buffer (unwind-protect (progn (select-window (car save-selected-window--state) 'norecord) (set-window-fringes window 0 0) (funcall query f n articles)) (internal--after-with-selected-window save-selected-window--state))))
  (progn (save-current-buffer (set-buffer (window-buffer summary-buffer-window)) (save-excursion (goto-char (window-start summary-buffer-window)) (let ((wend (window-end summary-buffer-window))) (while (< (point) wend) (if (memq (get-text-property ... ...) articles) (progn (let ... ... ...))) (forward-line 1))))) (let ((save-selected-window--state (internal--before-with-selected-window window))) (save-current-buffer (unwind-protect (progn (select-window (car save-selected-window--state) 'norecord) (set-window-fringes window 0 0) (funcall query f n articles)) (internal--after-with-selected-window save-selected-window--state)))))
  (unwind-protect (progn (save-current-buffer (set-buffer (window-buffer summary-buffer-window)) (save-excursion (goto-char (window-start summary-buffer-window)) (let ((wend (window-end summary-buffer-window))) (while (< (point) wend) (if (memq ... articles) (progn ...)) (forward-line 1))))) (let ((save-selected-window--state (internal--before-with-selected-window window))) (save-current-buffer (unwind-protect (progn (select-window (car save-selected-window--state) 'norecord) (set-window-fringes window 0 0) (funcall query f n articles)) (internal--after-with-selected-window save-selected-window--state))))) (mapc #'delete-overlay overlays))
  (let ((overlays 'nil)) (unwind-protect (progn (save-current-buffer (set-buffer (window-buffer summary-buffer-window)) (save-excursion (goto-char (window-start summary-buffer-window)) (let ((wend ...)) (while (< ... wend) (if ... ...) (forward-line 1))))) (let ((save-selected-window--state (internal--before-with-selected-window window))) (save-current-buffer (unwind-protect (progn (select-window ... ...) (set-window-fringes window 0 0) (funcall query f n articles)) (internal--after-with-selected-window save-selected-window--state))))) (mapc #'delete-overlay overlays)))
  (#f(lambda (window _v) [(summary-buffer-window #<window 3 on *Summary nnselect:search->subject--bug--from---*>) (articles (2139)) (n nil) (f #f(compiled-function (&optional n to-newsgroup select-method action) "Move the current article to a different newsgroup.\nIf N is a positive number, move the N next articles.\nIf N is a negative number, move the N previous articles.\nIf N is nil and any articles have been marked with the process mark,\nmove those articles instead.\nIf TO-NEWSGROUP is string, do not prompt for a newsgroup to move to.\nIf SELECT-METHOD is non-nil, do not move to a specific newsgroup, but\nre-spool using this method.\n\nWhen called interactively with TO-NEWSGROUP being nil, the value of\nthe variable `gnus-move-split-methods' is used for finding a default\nfor the target newsgroup.\n\nFor this function to work, both the current newsgroup and the\nnewsgroup that you want to move to have to support the `request-move'\nand `request-accept' functions.\n\nACTION can be either `move' (the default), `crosspost' or `copy'." (interactive "P") #<bytecode -0xa0099b9b29482be>)) (face nil) (query #f(lambda (f n _) [cl-struct-my-gnus-summary-process-marked-tags cl-struct-my-gnus-summary-pos-tags t] (funcall f n)))] (let ((overlays 'nil)) (unwind-protect (progn (save-current-buffer (set-buffer (window-buffer summary-buffer-window)) (save-excursion (goto-char ...) (let ... ...))) (let ((save-selected-window--state ...)) (save-current-buffer (unwind-protect ... ...)))) (mapc #'delete-overlay overlays)))) #<window 15 on  *Articles*> nil)
  (funcall #f(lambda (window _v) [(summary-buffer-window #<window 3 on *Summary nnselect:search->subject--bug--from---*>) (articles (2139)) (n nil) (f #f(compiled-function (&optional n to-newsgroup select-method action) "Move the current article to a different newsgroup.\nIf N is a positive number, move the N next articles.\nIf N is a negative number, move the N previous articles.\nIf N is nil and any articles have been marked with the process mark,\nmove those articles instead.\nIf TO-NEWSGROUP is string, do not prompt for a newsgroup to move to.\nIf SELECT-METHOD is non-nil, do not move to a specific newsgroup, but\nre-spool using this method.\n\nWhen called interactively with TO-NEWSGROUP being nil, the value of\nthe variable `gnus-move-split-methods' is used for finding a default\nfor the target newsgroup.\n\nFor this function to work, both the current newsgroup and the\nnewsgroup that you want to move to have to support the `request-move'\nand `request-accept' functions.\n\nACTION can be either `move' (the default), `crosspost' or `copy'." (interactive "P") #<bytecode -0xa0099b9b29482be>)) (face nil) (query #f(lambda (f n _) [cl-struct-my-gnus-summary-process-marked-tags cl-struct-my-gnus-summary-pos-tags t] (funcall f n)))] (let ((overlays 'nil)) (unwind-protect (progn (save-current-buffer (set-buffer (window-buffer summary-buffer-window)) (save-excursion (goto-char ...) (let ... ...))) (let ((save-selected-window--state ...)) (save-current-buffer (unwind-protect ... ...)))) (mapc #'delete-overlay overlays)))) #<window 15 on  *Articles*> nil)
  (if (functionp vquit-function) (funcall vquit-function window value) value)
  (let* ((vbuffer-or-name buffer) (vaction (list 'display-buffer-in-direction '(direction . top) (cons 'window-height #'fit-window-to-buffer) '(preserve-size nil . t) (cons 'body-function #'(lambda (_) (let ... ... ... ... ... ...) (remove-text-properties ... ... ...) (setq tab-line-exclude nil))))) (vquit-function #'(lambda (window _v) (let ((overlays ...)) (unwind-protect (progn ... ...) (mapc ... overlays))))) (buffer (temp-buffer-window-setup vbuffer-or-name)) (standard-output buffer) window value) (save-current-buffer (set-buffer buffer) (setq value (progn)) (setq window (temp-buffer-window-show buffer vaction))) (if (functionp vquit-function) (funcall vquit-function window value) value))
  (let ((buffer (get-buffer-create " *Articles*")) (article-table (my-print-table (mapcar #'(lambda (article-number) (let ... ...)) articles) (list #'(lambda (s) (propertize s ... ...))) '(nil right))) (window-min-height 1)) (let* ((vbuffer-or-name buffer) (vaction (list 'display-buffer-in-direction '(direction . top) (cons 'window-height #'fit-window-to-buffer) '(preserve-size nil . t) (cons 'body-function #'(lambda ... ... ... ...)))) (vquit-function #'(lambda (window _v) (let (...) (unwind-protect ... ...)))) (buffer (temp-buffer-window-setup vbuffer-or-name)) (standard-output buffer) window value) (save-current-buffer (set-buffer buffer) (setq value (progn)) (setq window (temp-buffer-window-show buffer vaction))) (if (functionp vquit-function) (funcall vquit-function window value) value)))
  (if (let ((buffer (get-buffer-create " *Articles*")) (article-table (my-print-table (mapcar #'(lambda ... ...) articles) (list #'(lambda ... ...)) '(nil right))) (window-min-height 1)) (let* ((vbuffer-or-name buffer) (vaction (list 'display-buffer-in-direction '(direction . top) (cons 'window-height #'fit-window-to-buffer) '(preserve-size nil . t) (cons 'body-function #'...))) (vquit-function #'(lambda (window _v) (let ... ...))) (buffer (temp-buffer-window-setup vbuffer-or-name)) (standard-output buffer) window value) (save-current-buffer (set-buffer buffer) (setq value (progn)) (setq window (temp-buffer-window-show buffer vaction))) (if (functionp vquit-function) (funcall vquit-function window value) value))) (progn (funcall body f n)))
  (let ((articles (sort (copy-sequence (gnus-summary-work-articles n)) #'<)) (gnus-novice-user nil) (summary-buffer-window (selected-window))) (if (let ((buffer (get-buffer-create " *Articles*")) (article-table (my-print-table (mapcar #'... articles) (list #'...) '(nil right))) (window-min-height 1)) (let* ((vbuffer-or-name buffer) (vaction (list 'display-buffer-in-direction '... (cons ... ...) '... (cons ... ...))) (vquit-function #'(lambda ... ...)) (buffer (temp-buffer-window-setup vbuffer-or-name)) (standard-output buffer) window value) (save-current-buffer (set-buffer buffer) (setq value (progn)) (setq window (temp-buffer-window-show buffer vaction))) (if (functionp vquit-function) (funcall vquit-function window value) value))) (progn (funcall body f n))))
  (progn (let ((articles (sort (copy-sequence (gnus-summary-work-articles n)) #'<)) (gnus-novice-user nil) (summary-buffer-window (selected-window))) (if (let ((buffer (get-buffer-create " *Articles*")) (article-table (my-print-table (mapcar ... articles) (list ...) '...)) (window-min-height 1)) (let* ((vbuffer-or-name buffer) (vaction (list ... ... ... ... ...)) (vquit-function #'...) (buffer (temp-buffer-window-setup vbuffer-or-name)) (standard-output buffer) window value) (save-current-buffer (set-buffer buffer) (setq value (progn)) (setq window (temp-buffer-window-show buffer vaction))) (if (functionp vquit-function) (funcall vquit-function window value) value))) (progn (funcall body f n)))))
  (unwind-protect (progn (let ((articles (sort (copy-sequence (gnus-summary-work-articles n)) #'<)) (gnus-novice-user nil) (summary-buffer-window (selected-window))) (if (let ((buffer (get-buffer-create " *Articles*")) (article-table (my-print-table ... ... ...)) (window-min-height 1)) (let* ((vbuffer-or-name buffer) (vaction ...) (vquit-function ...) (buffer ...) (standard-output buffer) window value) (save-current-buffer (set-buffer buffer) (setq value ...) (setq window ...)) (if (functionp vquit-function) (funcall vquit-function window value) value))) (progn (funcall body f n))))) (set-window-configuration wconfig))
  (let ((wconfig (current-window-configuration))) (unwind-protect (progn (let ((articles (sort (copy-sequence ...) #'<)) (gnus-novice-user nil) (summary-buffer-window (selected-window))) (if (let ((buffer ...) (article-table ...) (window-min-height 1)) (let* (... ... ... ... ... window value) (save-current-buffer ... ... ...) (if ... ... value))) (progn (funcall body f n))))) (set-window-configuration wconfig)))
  (#f(lambda (f &optional n &rest _) [(face nil) (body ignore) (query #f(lambda (f n _) [cl-struct-my-gnus-summary-process-marked-tags cl-struct-my-gnus-summary-pos-tags t] (funcall f n)))] (let ((wconfig (current-window-configuration))) (unwind-protect (progn (let ((articles ...) (gnus-novice-user nil) (summary-buffer-window ...)) (if (let ... ...) (progn ...)))) (set-window-configuration wconfig)))) #f(compiled-function (&optional n to-newsgroup select-method action) "Move the current article to a different newsgroup.\nIf N is a positive number, move the N next articles.\nIf N is a negative number, move the N previous articles.\nIf N is nil and any articles have been marked with the process mark,\nmove those articles instead.\nIf TO-NEWSGROUP is string, do not prompt for a newsgroup to move to.\nIf SELECT-METHOD is non-nil, do not move to a specific newsgroup, but\nre-spool using this method.\n\nWhen called interactively with TO-NEWSGROUP being nil, the value of\nthe variable `gnus-move-split-methods' is used for finding a default\nfor the target newsgroup.\n\nFor this function to work, both the current newsgroup and the\nnewsgroup that you want to move to have to support the `request-move'\nand `request-accept' functions.\n\nACTION can be either `move' (the default), `crosspost' or `copy'." (interactive "P") #<bytecode -0xa0099b9b29482be>) nil)
  (apply #f(lambda (f &optional n &rest _) [(face nil) (body ignore) (query #f(lambda (f n _) [cl-struct-my-gnus-summary-process-marked-tags cl-struct-my-gnus-summary-pos-tags t] (funcall f n)))] (let ((wconfig (current-window-configuration))) (unwind-protect (progn (let ((articles ...) (gnus-novice-user nil) (summary-buffer-window ...)) (if (let ... ...) (progn ...)))) (set-window-configuration wconfig)))) #f(compiled-function (&optional n to-newsgroup select-method action) "Move the current article to a different newsgroup.\nIf N is a positive number, move the N next articles.\nIf N is a negative number, move the N previous articles.\nIf N is nil and any articles have been marked with the process mark,\nmove those articles instead.\nIf TO-NEWSGROUP is string, do not prompt for a newsgroup to move to.\nIf SELECT-METHOD is non-nil, do not move to a specific newsgroup, but\nre-spool using this method.\n\nWhen called interactively with TO-NEWSGROUP being nil, the value of\nthe variable `gnus-move-split-methods' is used for finding a default\nfor the target newsgroup.\n\nFor this function to work, both the current newsgroup and the\nnewsgroup that you want to move to have to support the `request-move'\nand `request-accept' functions.\n\nACTION can be either `move' (the default), `crosspost' or `copy'." (interactive "P") #<bytecode -0xa0099b9b29482be>) nil)
  (gnus-summary-move-article nil)
  (funcall-interactively gnus-summary-move-article nil)
  (call-interactively gnus-summary-move-article nil nil)
  (command-execute gnus-summary-move-article)

This happens only when using `gnus-move-split-methods' nil.  When I use
a value like

 ((".*" . ("nnml+archive:emacs" ...)))

the error does not happen and the operation succeeds.  Although I choose
the same target group in both cases.

It was very hard to debug why that setting influences the result.  I
followed the problem to a call to `nnselect-article-number' - here:

|   (nnselect-article-number 2140)
|   (cl-mapcan #f(lambda (act) [t] (let* ((--cl-rest-- act) (range (if (= (length --cl-rest--) 3) (car-safe (prog1 --cl-rest-- (setq --cl-rest-- (cdr --cl-rest--)))) (signal 'wrong-number-of-arguments (list '(range action marks) (length --cl-rest--))))) (action (car-safe (prog1 --cl-rest-- (setq --cl-rest-- (cdr --cl-rest--))))) (marks (car-safe --cl-rest--))) (mapcar #'(lambda (artgroup) (list (car artgroup) (gnus-compress-sequence (sort (cdr artgroup) #'<)) action marks)) (cond ((eq 'range 'range) (let* ((sequence (range-uncompress range))) (let ((valuefunc (or #'nnselect-article-number 'identity)) result) (if (null sequence) nil (mapc #'(lambda (member) (let* ((key (elt (if (> member 0) (progn (elt gnus-newsgroup-selection (1- member)))) 0)) (value (funcall valuefunc member)) (kr (assoc key result))) (if kr (let* ((v kr)) (setcdr v (cons value (cdr v)))) (setq result (cons (list key value) result))))) (reverse sequence)) result)))) ((eq 'range 'tuple) (let* ((keyfunc #'(lambda (elem) (elt (if (> (car elem) 0) (progn (elt gnus-newsgroup-selection (1- (car elem))))) 0))) (valuefunc #'(lambda (elem) (cons (elt (if (> (car elem) 0) (progn (elt gnus-newsgroup-selection (1- (car elem))))) 1) (cdr elem))))) (let ((valuefunc (or valuefunc 'identity)) result) (if (null range) nil (mapc #'(lambda (member) (let* ((key (funcall keyfunc member)) (value (funcall valuefunc member)) (kr (assoc key result))) (if kr (let* ((v kr)) (setcdr v (cons value (cdr v)))) (setq result (cons (list key value) result))))) (reverse range)) result)))) (t (let ((valuefunc (or #'nnselect-article-number 'identity)) result) (if (null range) nil (mapc #'(lambda (member) (let* ((key (elt (if (> member 0) (progn (elt gnus-newsgroup-selection (1- member)))) 0)) (value (funcall valuefunc member)) (kr (assoc key result))) (if kr (let* ((v kr)) (setcdr v (cons value (cdr v)))) (setq result (cons (list key value) result))))) (reverse range)) result))))))) (((2140) set nil) ((2140) del (unexist seen forward unsend download cache save score dormant bookmark killed expire reply tick))))
|   (nnselect-request-set-mark "search->subject--bug--from---" (((2140) set nil) ((2140) del (unexist seen forward unsend download cache save score dormant bookmark killed expire reply tick))) "nnselect-ephemeral")
|   (gnus-request-set-mark "nnselect:search->subject--bug--from---" (((2140) set nil) ((2140) del (unexist seen forward unsend download cache save score dormant bookmark killed expire reply tick))))
|   (gnus-summary-push-marks-to-backend 2140)
|   (gnus-summary-move-article nil)

In the good case this returns a number, in the bad case `nil'.  This is
where the `nil' in the backtrace above seems to come from.  But I don't
understand why that happens.  Could be `gnus-newsgroup-selection' that
has a different value, but I gave up at that point - too many
`define-inline' definitions related and I don't know if I'm on the right
track anyway.

Anybody any ideas?

TIA,

Michael.

In GNU Emacs 31.0.50 (build 16, x86_64-pc-linux-gnu, cairo version
 1.16.0) of 2024-09-02 built on drachen
Repository revision: 6975d13525148306e1825bb881560c6b6b989cf8
Repository branch: master
Windowing system distributor 'The X.Org Foundation', version 11.0.12101007
System Description: Debian GNU/Linux 12 (bookworm)