Describe the bug
When the khoj server is unreachable, khoj.el's failed-request handler kills unrelated Emacs processes — including the emacsclient server listener, whose socket file is then removed by server-sentinel. The practical symptom: ~60 seconds after starting Emacs (when the auto-index timer first fires), emacsclient stops working with can't find socket; have you started the server?, and every hourly re-index kills any manually restarted server again. Buffer-less processes other than the server listener (e.g. live emacsclient connections) are killed too.
Root cause
khoj--delete-open-network-connections-to-server (khoj.el:1118, v2.0.0-beta.28) iterates the whole process-list and matches each process by the name of its buffer:
(defun khoj--delete-open-network-connections-to-server ()
"Delete all network connections to khoj server."
(dolist (proc (process-list))
(let ((proc-buf (buffer-name (process-buffer proc)))
(khoj-network-proc-buf (string-join (split-string khoj-server-url "://") " ")))
(when (string-match (format "%s" khoj-network-proc-buf) proc-buf)
(ignore-errors (delete-process proc))))))
Two problems combine:
- Many processes have no buffer (
process-buffer → nil), and (buffer-name nil) returns the name of the current buffer — it does not error.
- This function is called from the
url-retrieve failure callback in khoj--send-index-update-request (khoj.el:447), where the current buffer is the failed url-http buffer, e.g. *http localhost:42110* — which matches the "http localhost:42110" pattern.
So every buffer-less process in the session matches and gets delete-processd. That includes the server-start listener process; deleting it flips its status to closed, and server-sentinel then deletes the server socket file.
The deletions also cascade: deleting one pending url-http process fires its sentinel, which invokes the failure callback and khoj--delete-open-network-connections-to-server again, recursively.
To Reproduce
- Configure khoj.el with
khoj-auto-index enabled (the default) and a khoj-server-url pointing at a server that is not running.
- Start Emacs with
server-start (or a daemon), verify emacsclient --eval t works.
- Wait for the first auto-index run (60s), or trigger
M-x khoj--server-index-files manually.
emacsclient now fails with can't find socket; lsof -U -a -p <emacs-pid> shows the listening socket fd is gone, and the socket file has been removed.
Backtrace captured with advice on delete-process at the moment the listener dies:
delete-process(#<process server>) ; ← the Emacs server listener
khoj--delete-open-network-connections-to-server()
#f(compiled-function (status) ...)((:error (error connection-failed "deleted\n" :host "localhost" :service 42110)))
url-http-activate-callback()
url-http-async-sentinel(#<process localhost> "deleted\n")
Suggested fix
Only consider processes that actually own a live buffer:
(defun khoj--delete-open-network-connections-to-server ()
"Delete all network connections to khoj server."
(let ((khoj-network-proc-buf (string-join (split-string khoj-server-url "://") " ")))
(dolist (proc (process-list))
(let ((buf (process-buffer proc)))
(when (and buf
(buffer-live-p buf)
(string-match-p khoj-network-proc-buf (buffer-name buf)))
(ignore-errors (delete-process proc)))))))
Optionally, khoj--server-index-files could also skip the index run entirely (with a message) when a quick /api/health check fails, instead of building and sending the full multipart body only to fail per batch.
Platform
- Server: Docker (server not running is the trigger)
- Client: Emacs 30.2, khoj.el 2.0.0-beta.28 (macOS)
If applicable, share the file type you were trying to index
org-mode (irrelevant to the bug — any failed index request triggers it)
Describe the bug
When the khoj server is unreachable,
khoj.el's failed-request handler kills unrelated Emacs processes — including the emacsclient server listener, whose socket file is then removed byserver-sentinel. The practical symptom: ~60 seconds after starting Emacs (when the auto-index timer first fires),emacsclientstops working withcan't find socket; have you started the server?, and every hourly re-index kills any manually restarted server again. Buffer-less processes other than the server listener (e.g. live emacsclient connections) are killed too.Root cause
khoj--delete-open-network-connections-to-server(khoj.el:1118, v2.0.0-beta.28) iterates the wholeprocess-listand matches each process by the name of its buffer:Two problems combine:
process-buffer→nil), and(buffer-name nil)returns the name of the current buffer — it does not error.url-retrievefailure callback inkhoj--send-index-update-request(khoj.el:447), where the current buffer is the failed url-http buffer, e.g.*http localhost:42110*— which matches the"http localhost:42110"pattern.So every buffer-less process in the session matches and gets
delete-processd. That includes theserver-startlistener process; deleting it flips its status toclosed, andserver-sentinelthen deletes the server socket file.The deletions also cascade: deleting one pending url-http process fires its sentinel, which invokes the failure callback and
khoj--delete-open-network-connections-to-serveragain, recursively.To Reproduce
khoj-auto-indexenabled (the default) and akhoj-server-urlpointing at a server that is not running.server-start(or a daemon), verifyemacsclient --eval tworks.M-x khoj--server-index-filesmanually.emacsclientnow fails withcan't find socket;lsof -U -a -p <emacs-pid>shows the listening socket fd is gone, and the socket file has been removed.Backtrace captured with advice on
delete-processat the moment the listener dies:Suggested fix
Only consider processes that actually own a live buffer:
Optionally,
khoj--server-index-filescould also skip the index run entirely (with a message) when a quick/api/healthcheck fails, instead of building and sending the full multipart body only to fail per batch.Platform
If applicable, share the file type you were trying to index
org-mode (irrelevant to the bug — any failed index request triggers it)