I'm facing a strange issue and I don't know how to debug it. In the middle of work after-change-functions just gets set to nil. I use doom-modeline and it installs hooks to after-change-functions to update buffer state (whether it's modified or not). So when it happens, doom-modeline stops showing buffer actual state. Re-adding hooks to after-change-functions restores normal functionality, but after some time this might happen again. What could be the issue? Emacs v26.1 from Debian repos. My init.el:

(require 'package)
(let* ((no-ssl (and (memq system-type '(windows-nt ms-dos))
                    (not (gnutls-available-p))))
       (proto (if no-ssl "http" "https")))
  (when no-ssl
    (warn "\
Your version of Emacs does not support SSL connections,
which is unsafe because it allows man-in-the-middle attacks.
There are two things you can do about this warning:
1. Install an Emacs version that does support SSL and be safe.
2. Remove this warning from your init file so you won't see it again."))
  ;; Comment/uncomment these two lines to enable/disable MELPA and MELPA Stable as desired
  (add-to-list 'package-archives (cons "melpa" (concat proto "://melpa.org/packages/")) t)
  ;;(add-to-list 'package-archives (cons "melpa-stable" (concat proto "://stable.melpa.org/packages/")) t)
  (when (< emacs-major-version 24)
    ;; For important compatibility libraries like cl-lib
    (add-to-list 'package-archives (cons "gnu" (concat proto "://elpa.gnu.org/packages/")))))

;; Added by Package.el.  This must come before configurations of
;; installed packages.  Don't delete this line.  If you don't want it,
;; just comment it out by adding a semicolon to the start of the line.
;; You may delete these explanatory comments.

(setq custom-file (concat user-emacs-directory "/custom.el"))
(load-file custom-file)

(unless package-archive-contents

(unless (display-graphic-p)
  (require 'terminal-focus-reporting)

(defun server-shutdown ()
  "Save buffers, Quit, and Shutdown (kill) server"

(defun save-current-buffer-if-needed ()
  (when (and (buffer-file-name) (buffer-modified-p))

(add-hook 'focus-out-hook 'save-current-buffer-if-needed)
(add-hook 'focus-in-hook 'diff-hl-update)
(add-hook 'prog-mode-hook 'fci-mode); set long line ruler
(add-hook 'git-commit-mode-hook 'fci-mode)
(add-hook 'prog-mode-hook (lambda () (setq indent-tabs-mode t)))

(setq org-agenda-files '("~/doc/notes"))
(setq org-pomodoro-length 30)
(setq org-pomodoro-long-break-length 30)
(setq org-pomodoro-manual-break t)
(setq org-pomodoro-expiry-time 60)
(setq org-pomodoro-format "Pomodoro - %s")
(setq org-pomodoro-short-break-format "Short - %s")
(setq org-pomodoro-long-break-format "Long - %s")
(setq org-pomodoro-overtime-format "Overtime - %s")

(global-anzu-mode); show total matches in find/replace
(dtrt-indent-global-mode); figure out file indentation
(smart-tabs-insinuate 'c 'c++)
(menu-bar-mode -1)
(tool-bar-mode -1)
(scroll-bar-mode -1)
(horizontal-scroll-bar-mode -1)
(diff-hl-margin-mode); use margin for diff signs
(diff-hl-flydiff-mode); on-the-fly highlighting (without having to save file)

(add-to-list 'default-frame-alist
             '(font . "Terminus-10"))

(setq-default global-mode-string
              '(:eval (format "%dL" total-lines)))
(setq-default tab-width 4)
(setq-default indent-tabs-mode nil)
(setq-default c-basic-offset 4)
(setq-default auto-save-default nil)
(setq-default make-backup-files nil)
(setq-default require-final-newline t)
(setq-default projectile-switch-project-action 'helm-projectile)
(setq-default show-trailing-whitespace t)
(setq-default scroll-conservatively 101)
(setq-default echo-keystrokes 0.01)
(setq-default git-commit-summary-max-length 50)
(setq-default column-number-indicator-zero-based nil)
(setq-default fci-rule-column 80)
(setq-default create-lockfiles nil)
(setq-default org-log-done 'note)
(setq-default org-startup-indented t)
(setq-default find-file-visit-truename t)
(setq whitespace-style '(face trailing))

;(whole-line-or-region-global-mode t)
(line-number-mode -1)
(setq linum-format "%4d ")

(load-file (concat user-emacs-directory "keys.el"))

(defun inhibit-save-message (f &rest args)
  (let ((inhibit-message t))
    (funcall f)))

(advice-add 'save-buffer :around #'inhibit-save-message)

(doom-modeline-def-modeline 'my-simple-line
  '(bar matches buffer-info remote-host buffer-position parrot selection-info)
  '(misc-info minor-modes input-method buffer-encoding major-mode process vcs checker))

(defun setup-custom-doom-modeline ()
  (doom-modeline-set-modeline 'my-simple-line 'default))

(add-hook 'doom-modeline-mode-hook 'setup-custom-doom-modeline)
  • Off-topic, but your inhibit-save-message should use (apply f args), instead of funcall. – npostavs Jun 21 '19 at 10:45
  • @npostavs It's like he never calls save-buffer with prefix-args. (funcall f) is brute but it should work. Your comment is more like an advice for good style. – Tobias Jun 21 '19 at 11:06

For answering why after-change-functions becomes nil I cite a paragraph of the doc-string of after-change-functions:

If an unhandled error happens in running these functions, the variable's value remains nil. That prevents the error from happening repeatedly and making Emacs nonfunctional.

Turn on the switch "Enter Debugger on Error" in the "Options" menu. If that switch is on you should get a backtrace when the error happens next time.

If the problem becomes kind of long-term investigation you can also set debug-on-error to t in your init file for that period.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.