patch 9.2.0999: serverlist() fails when there is no connection to the server
Commit:
https://github.com/vim/vim/commit/46073443359365778d673eda255a90282060d7d7
Author: thinca <
thi...@gmail.com>
Date: Sun Aug 23 19:24:57 2026 +0000
patch 9.2.0999: serverlist() fails when there is no connection to the server
Problem: Since patch 9.2.0818, serverlist() gives E240 instead of
returning an empty result when the X11 clientserver backend
cannot connect to the X server, e.g. on a Wayland-only system.
This contradicts the documentation and patches 6.0.191 and
6.1.349, which deliberately removed that error message. On
the failing path the return value is a Number as well.
Solution: Do not give an error when the X server cannot be reached, but
return an empty string, or an empty List when the "list"
option is used. The "list" option now always results in a
List when no server names are available, which is the type
inconsistency that patch 9.2.0818 set out to fix.
related: #20716
closes: #21124
Co-authored-by: Claude <
nor...@anthropic.com>
Signed-off-by: thinca <
thi...@gmail.com>
Signed-off-by: Christian Brabandt <
c...@256bit.org>
diff --git a/runtime/doc/builtin.txt b/runtime/doc/builtin.txt
index 9effcec54..0228bcbd6 100644
--- a/runtime/doc/builtin.txt
+++ b/runtime/doc/builtin.txt
@@ -1,4 +1,4 @@
-*builtin.txt* For Vim version 9.2. Last change: 2026 Aug 20
+*builtin.txt* For Vim version 9.2. Last change: 2026 Aug 23
VIM REFERENCE MANUAL by Bram Moolenaar
@@ -9929,7 +9929,11 @@ server2client({clientid}, {string}) *server2client()*
serverlist([{dict}]) *serverlist()*
Return a list of available server names, one per line.
When there are no servers or the information is not available
- an empty string is returned.
+ an empty string is returned, or an empty |List| when the
+ "list" option below is used.
+
+ When the server cannot be reached, no error will be given and
+ the result is an empty string or |List|.
{only available when compiled with the |+clientserver| feature}
If {dict} is given, then it is a |Dictionary| supporting the
diff --git a/src/clientserver.c b/src/clientserver.c
index 30aab970f..9a099e7b0 100644
--- a/src/clientserver.c
+++ b/src/clientserver.c
@@ -1284,18 +1284,19 @@ f_serverlist(typval_T *argvars UNUSED, typval_T *rettv)
# ifdef FEAT_X11
if (clientserver_method == CLIENTSERVER_METHOD_X11)
{
- // This function fails if there is no X11 connection.
- if (check_connection() == FAIL)
- return;
- // If the check_connection() function returns OK, it has already been
- // confirmed within that function that make_connection() was called and
- // that X_DISPLAY is not NULL.
- list = serverGetVimNames(X_DISPLAY);
+ make_connection();
+ if (X_DISPLAY != NULL)
+ list = serverGetVimNames(X_DISPLAY);
}
# endif
# endif
- if (use_list && list != NULL)
+ if (use_list)
{
+ if (list == NULL)
+ {
+ (void)rettv_list_alloc(rettv);
+ return;
+ }
list->lv_refcount++;
rettv->v_type = VAR_LIST;
rettv->vval.v_list = list;
diff --git a/src/testdir/test_clientserver.vim b/src/testdir/test_clientserver.vim
index 5ed063e1f..17ea44d41 100644
--- a/src/testdir/test_clientserver.vim
+++ b/src/testdir/test_clientserver.vim
@@ -708,20 +708,24 @@ func Test_clientserver_serverlist_without_x11()
throw 'GetVimCommand() failed'
endif
- " This test verifies that serverlist() fails with error E240 when a
+ " This test verifies that serverlist() returns an empty result when a
" connection to X11 cannot be established. It must be executed with the
" CLIENTSERVER backend set to x11 and in a state where the X11 server is
" unreachable.
"
" To achieve this, the `VIM_CLIENTSERVER` and `DISPLAY` environment
- " variables must be unset before running Vim as a child process. Within the
- " child process, `assert_fails()` and `v:errors` are used to confirm that
- " E240 occurred; if E240 is raised as expected, `v:errors` remains empty,
- " whereas if the call succeeds or a different error occurs, `v:errors` will
- " contain one or more errors.
+ " variables must be unset before running Vim as a child process. The child
+ " process reports the number of `v:errors` as its exit code. The calls are
+ " wrapped in a try/catch, because an error would otherwise skip the
+ " assertion without adding anything to `v:errors`.
call writefile([
- \ "call assert_fails('let x = serverlist()', 'E240:')",
+ \ "try",
+ \ " call assert_equal('', serverlist())",
+ \ " call assert_equal([], serverlist(#{list: v:true}))",
+ \ "catch",
+ \ " call add(v:errors, 'unexpected exception: ' .. v:exception)",
+ \ "endtry",
\ "execute 'cq! ' .. len(v:errors)"
\ ], 'Xtest', 'D')
diff --git a/src/testdir/test_vim9_builtin.vim b/src/testdir/test_vim9_builtin.vim
index a32fe559b..adbb03495 100644
--- a/src/testdir/test_vim9_builtin.vim
+++ b/src/testdir/test_vim9_builtin.vim
@@ -3631,14 +3631,10 @@ def Test_remote_serverlist()
v9.CheckSourceDefAndScriptFailure(['serverlist("")'], ['E1013: Argument 1: type mismatch, expected dict<any> but got string', 'E1206: Dictionary required for argument 1'])
v9.CheckSourceScriptFailure(['vim9script', 'serverlist({list: ""})'], 'E1135: Using a String as a Bool: ""')
- try
- var l: any = serverlist()
- assert_equal(v:t_string, type(l))
- l = serverlist({'list': true})
- assert_equal(v:t_list, type(l))
- catch /E240:/
- # ignore no connection to the X server
- endtry
+ var l: any = serverlist()
+ assert_equal(v:t_string, type(l))
+ l = serverlist({'list': true})
+ assert_equal(v:t_list, type(l))
enddef
def Test_remove_literal_list()
diff --git a/src/version.c b/src/version.c
index d33f63fed..5e5717f9a 100644
--- a/src/version.c
+++ b/src/version.c
@@ -763,6 +763,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
+/**/
+ 999,
/**/
998,
/**/