bug#81610: 30.2; [PATCH] NS; NSRangeException when enabling tool-bar-mode

Yavor Doganov <[email protected]>
Newsgroups gmane.emacs.bugs
Organization The GNU Emacs Church (Bulgarian Eparchy)
Message-ID <87mrurbg1t.GNU'[email protected]>
If I customize the tool-bar-mode variable to nil then the toolbar is
not displayed, as expected.  However, if I enable it explicitly with
the interactive command, an exception is thrown: a dialog "Critical
Error in emacs" appears containing "NSRangeException: Index 0 is out
of range 0 (in 'objectAtIndex:')".  Emacs then aborts.

Steps to reproduce:

  1. emacs -Q --eval "(tool-bar-mode -1)"
  2. M-x tool-bar-mode RET

Backtrace and proposed patch below based on the master branch.

In GNU Emacs 30.2 (build 2, x86_64-pc-linux-gnu, NS
 gnustep-gui-0.32.0) of 2026-07-04, modified by Debian built on
 patilan
Windowing system distributor 'GNU', version 10.3.32
System Description: Debian GNU/Linux forky/sid

Configured using:
 'configure --build x86_64-linux-gnu --prefix=/usr
 --sharedstatedir=/var/lib --libexecdir=/usr/libexec
 --localstatedir=/var/lib --infodir=/usr/share/info
 --mandir=/usr/share/man --with-libsystemd --with-pop=yes
 --enable-locallisppath=/etc/emacs:/usr/local/share/emacs/30.2/site-lisp:/usr/local/share/emacs/site-lisp:/usr/share/emacs/30.2/site-lisp:/usr/share/emacs/site-lisp
 --with-sound=alsa --without-gconf --with-mailutils --build
 x86_64-linux-gnu --prefix=/usr --sharedstatedir=/var/lib
 --libexecdir=/usr/libexec --localstatedir=/var/lib
 --infodir=/usr/share/info --mandir=/usr/share/man --with-libsystemd
 --with-pop=yes
 --enable-locallisppath=/etc/emacs:/usr/local/share/emacs/30.2/site-lisp:/usr/local/share/emacs/site-lisp:/usr/share/emacs/30.2/site-lisp:/usr/share/emacs/site-lisp
 --with-sound=alsa --without-gconf --with-mailutils --with-ns
 --disable-ns-self-contained --without-gif --without-jpeg
 --without-png --without-rsvg --without-tiff --without-webp 'CFLAGS=-g
 -O2 -Werror=implicit-function-declaration
 -ffile-prefix-map=/build/reproducible-path/emacs-30.2+1=. -fstack-protector-strong
 -fstack-clash-protection -Wformat -Werror=format-security
 -fcf-protection -Wall' 'CPPFLAGS=-Wdate-time -D_FORTIFY_SOURCE=2'
 LDFLAGS=-Wl,-z,relro'

Configured features:
ACL DBUS GMP GNUTLS GPM LCMS2 LIBSELINUX LIBSYSTEMD LIBXML2 MODULES
NATIVE_COMP NOTIFY INOTIFY NS PDUMPER SECCOMP SOUND SQLITE3 THREADS
TOOLKIT_SCROLL_BARS TREE_SITTER XIM ZLIB

(gdb) break -[NSException raise]
❌️ Function "-[NSException raise]" not defined.
Make breakpoint pending on future shared library load? (y or [n]) y
Breakpoint 1 (-[NSException raise]) pending.
(gdb) r -Q --eval "(tool-bar-mode -1)"
Starting program: /home/yavor/src/emacs/src/emacs -Q --eval "(tool-bar-mode -1)"
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/usr/lib/x86_64-linux-gnu/libthread_db.so.1".
⚠️ warning: Corrupted shared library list: 0x5555564e04b0 != 0x5555564df930
[New Thread 0x7fffe8d5e6c0 (LWP 246730)]

Thread 1 "emacs" hit Breakpoint 1, -[NSException raise] (self=0x5555574f8030, 
    _cmd=0x7ffff758d640 <_OBJC_SELECTOR_TABLE+128>)
    at ./Source/NSException.m:1602
⚠️ warning: 1602	./Source/NSException.m: Няма такъв файл или директория
(gdb) bt
#0  -[NSException raise]
    (self=0x5555574f8030, _cmd=0x7ffff758d640 <_OBJC_SELECTOR_TABLE+128>)
    at ./Source/NSException.m:1602
#1  0x00007ffff71c02b4 in -[GSArray objectAtIndex:]
    (self=0x555557b78bc0, _cmd=<optimized out>, index=0)
    at ./Source/GSArray.m:355
#2  0x00007ffff7c1dddd in -[NSToolbar _removeItemAtIndex:broadcast:]
    (self=0x555557a87500, _cmd=<optimized out>, index=0, broadcast=0 '\000')
    at ./Source/NSToolbar.m:1270
#3  0x00007ffff7c1dfed in -[NSToolbar _removeItemAtIndex:broadcast:]
    (self=0x555557fb5980, _cmd=<optimized out>, index=0, broadcast=<optimized out>) at ./Source/NSToolbar.m:1284
#4  0x0000555555851b79 in -[EmacsToolbar clearAll]
    (self=0x555557fb5980, _cmd=<optimized out>) at nsmenu.m:1310
#5  0x00005555558569de in update_frame_tool_bar_1
    (f=0x5555560725a0, toolbar=0x555557fb5980) at nsmenu.m:1133
#6  0x0000555555662e44 in redisplay_window
    (window=0x5555560f1105, just_this_one_p=just_this_one_p@entry=false)
    at xdisp.c:21545
#7  0x0000555555663adb in redisplay_window_0 (window=<optimized out>)
    at xdisp.c:18531
#8  0x0000555555773a29 in internal_condition_case_1
    (bfun=bfun@entry=0x555555663ab0 <redisplay_window_0>, arg=0x5555560f1105, handlers=<optimized out>, hfun=hfun@entry=0x5555556149b0 <redisplay_window_error>) at eval.c:1736
#9  0x0000555555611c85 in redisplay_windows (window=0x5555560f1105)
    at xdisp.c:18500
#10 0x0000555555647cc0 in redisplay_internal () at xdisp.c:17917
#11 0x0000555555649b75 in redisplay () at xdisp.c:17063
#12 0x00005555556f0582 in read_char
    (commandflag=<optimized out>, map=map@entry=0x7fffecf61563, prev_event=<optimized out>, used_mouse_menu=used_mouse_menu@entry=0x7fffffffd76b, end_time=end_time@entry=0x0) at keyboard.c:2711
#13 0x00005555556f35e3 in read_key_sequence
    (keybuf=keybuf@entry=0x7fffffffd8b0, prompt=prompt@entry=0x0, dont_downcase_last=dont_downcase_last@entry=false, can_return_switch_frame=can_return_switch_frame@entry=true, fix_current_buffer=fix_current_buffer@entry=true, prevent_redisplay=prevent_redisplay@entry=false, disable_text_conversion_p=false)
    at keyboard.c:11224
#14 0x00005555556f5754 in command_loop_1 () at keyboard.c:1424
#15 0x00005555557739a4 in internal_condition_case
    (bfun=bfun@entry=0x5555556f55a0 <command_loop_1>, handlers=handlers@entry=0x90, hfun=hfun@entry=0x5555556e7b30 <cmd_error>) at eval.c:1712
#16 0x00005555556df366 in command_loop_2 (handlers=0x90) at keyboard.c:1163
#17 0x00005555557738fe in internal_catch
    (tag=tag@entry=0x12270, func=func@entry=0x5555556df340 <command_loop_2>, arg=arg@entry=0x90) at eval.c:1392
#18 0x00005555556df303 in command_loop () at keyboard.c:1141
#19 0x00005555556e76e1 in recursive_edit_1 () at keyboard.c:749
#20 0x00005555556e7a68 in Frecursive_edit () at keyboard.c:832
#21 0x00005555555f1de8 in main (argc=<optimized out>, argv=<optimized out>)
    at emacs.c:2635
(gdb) fr 3
#3  0x00007ffff7c1dfed in -[NSToolbar _removeItemAtIndex:broadcast:] (
    self=0x555557fb5980, _cmd=<optimized out>, index=0, 
    broadcast=<optimized out>) at ./Source/NSToolbar.m:1284
⚠️ warning: 1284	./Source/NSToolbar.m: Няма такъв файл или директория
(gdb) po self
<EmacsToolbar: 0x555557fb5980>
(gdb) po _items
("<<NSToolbarItem: 0x555557fb5210> - <5864062930753Open>>", "<<NSToolbarItem: 0x555557fb4ac0> - <5864062916976Open Directory>>", "<<NSToolbarItem: 0x555557fb42f0> - <5864062922955Close>>", "<<NSToolbarItem: 0x555557fb3b20> - <5864062924951Save>>", "<<NSToolbarItem: 0x555557fb3350> - <5864062937190Undo>>", "<<NSToolbarItem: 0x555557fb2b80> - <5864062939314Cut>>", "<<NSToolbarItem: 0x555557fb23b0> - <5864062940411Copy>>", "<<NSToolbarItem: 0x555557fb1bc0> - <5864063816493Paste>>", "<<NSToolbarItem: 0x555557fb13f0> - <5864064151308Search>>")
(gdb) down
#2  0x00007ffff7c1dddd in -[NSToolbar _removeItemAtIndex:broadcast:] (
    self=0x555557a87500, _cmd=<optimized out>, index=0, broadcast=0 '\000')
    at ./Source/NSToolbar.m:1270
1270	in ./Source/NSToolbar.m
(gdb) po self
<EmacsToolbar: 0x555557a87500>
(gdb) po _items
()

Notice that in GDB frames 2 and 3 there are two distinct EmacsToolbar
instances for a single Emacs frame.  The one from GDB frame 2,
0x555557a87500, is a "parasite" object: it is initialized at frame
creation and toolbar items are never insterted in it.

GNUstep's NSToolbar implementation of -removeItemAtIndex: (called from
EmacsToolbar -clearAll, nsmenu.m:1310) calls the private method
-_removeItemAtIndex:broadcast: which calls itself recursively,
dispatching the method call to all instances of the same class with
identical identifiers (see the TRANSMIT macro definition in
gnustep-gui/Source/NSToolbar.m:1205).  The goal here is to update the
toolbars of the app's other windows ("frames" in Emacs terminology) if
the identifiers match.

Because this first EmacsToolbar instance doesn't have any toolbar
items, an exception occurs.
0001-NS-Fix-NSRangeException-when-enabling-tool-bar-mode.patch (text/plain, 779 B)
From 000bcd06ea7430485a6796a7c3fd032be7566103 Mon Sep 17 00:00:00 2001
From: Yavor Doganov <[email protected]>
Date: Wed, 12 Aug 2026 16:44:33 +0300
Subject: [PATCH] NS: Fix NSRangeException when enabling tool-bar-mode

* src/nsmenu.m (free_frame_tool_bar): Don't call EmacsWindow
-setToolbar: with a nil argument; fixes NSRangeException when
enabling tool-bar-mode.  (Bug#-1)
---
 src/nsmenu.m | 2 --
 1 file changed, 2 deletions(-)

diff --git a/src/nsmenu.m b/src/nsmenu.m
index ab6e7d7140d..a8177b95f35 100644
--- a/src/nsmenu.m
+++ b/src/nsmenu.m
@@ -1110,8 +1110,6 @@ - (NSRect)confinementRectForMenu:(NSMenu *)menu
   [[[view window] toolbar] setVisible:NO];
   f->output_data.ns->in_animation = 0;
 
-  [[view window] setToolbar:nil];
-
   unblock_input ();
 }
 
-- 
2.55.0
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.