This problem started happening today when I switched to my desktop computer after a couple months of using my laptop. I updated emacs to 25.3.1, updated all my packages, and downloaded my latest .emacs, the one that I had been using on my laptop.

When I run M-x magit-status, I get the following message:

user-error: Whitespace-Mode isn’t compatible with Magit.  See `magit-diff-paint-whitespace' for an alternative.

This only happens after I run (global-whitespace-mode 1) to enable visible whitespace everywhere. When I run (global-whitespace-mode 0) then I can run magit-status but lose global whitespace.

  • Nothing changed on Magit's side, but three people reported this over the last 24 hours. Do you use some starter-kit? ... ah wait ... two of them are you ;-)
    – tarsius
    Feb 12 '18 at 11:36
  • Incidentally, I can't replicate this problem with the current version of Magit on MELPA.
    – phils
    Feb 13 '18 at 5:01
  • Cross-referencing with the associated issue on Github: github.com/magit/magit/issues/3374
    – phils
    Feb 13 '18 at 5:02

I just added the following to my init.el:

(defun prevent-whitespace-mode-for-magit ()
  (not (derived-mode-p 'magit-mode)))

(add-function :before-while whitespace-enable-predicate 'prevent-whitespace-mode-for-magit)

This basically advises the function whitespace-enable-predicate, which whitespace-mode uses to determine, which buffers should receive global-whitespace-mode (and which is confusingly a variable holding a function as a value, not a named function, hence the add-function instead of advice-add, and no quote in front of its name; we want the value). We just ask whether we are in a magit derived mode, here. The :before-while basically assures that in all the other cases, the original behavior of whitespace-enable-predicate is preserved; see the documentation of add-function for more details.


You could customize the whitespace-global-modes variable to be:

(not magit-mode)

Edit: In fact, as pointed out by Julian Kniephoff in the comments, this would have to be a more complete list of magit modes, which is pretty cumbersome, and would need maintaining. Something like:

 magit-mode magit-cherry-mode magit-diff-mode magit-log-mode
 magit-log-select-mode magit-merge-preview-mode
 magit-process-mode magit-reflog-mode magit-refs-mode
 magit-repolist-mode magit-revision-mode magit-stash-mode
 magit-stashes-mode magit-status-mode magit-submodule-list-mode)

With that in mind, I couldn't really recommend this approach.

Edit 2: I don't recommend the following either (it's way too fiddly compared to just using advice), but if you particularly wanted to keep this variable populated dynamically using only hooks...

(setq whitespace-global-modes '(not magit-mode))

(defun my-inhibit-whitespace-mode-maybe ()
  "Inhibit `global-whitespace-mode' for certain modes.

Used in `after-change-major-mode-hook', but before the global
mode is processed."
  (when (derived-mode-p 'magit-mode)
    (add-to-list 'whitespace-global-modes major-mode :append)))

(defun my-global-whitespace-mode-hook ()
  "Custom behaviours for `global-whitespace-mode'."
  ;; n.b. We need `my-inhibit-whitespace-mode-maybe' to act before
  ;; `whitespace-turn-on-if-enabled' in `after-change-major-mode-hook'.
  (remove-hook 'after-change-major-mode-hook 'my-inhibit-whitespace-mode-maybe)
  (when global-whitespace-mode
    (add-hook 'after-change-major-mode-hook 'my-inhibit-whitespace-mode-maybe)))

(add-hook 'global-whitespace-mode-hook 'my-global-whitespace-mode-hook)

(global-whitespace-mode 1)
  • I tired that, too, but it did not work for me. Probably because the typical magit buffers (like magit-status) are not actually in magit-mode, but rather in a derived mode (for example magit-status-mode). whitespace-global-modes seems to work only with exact matches. Feb 12 '18 at 8:41
  • Right, that makes sense.
    – phils
    Feb 12 '18 at 11:10
  • I guess you could compute the list with something like (let ((modes nil)) (mapatoms (lambda (m) (when (provided-mode-derived-p m 'magit-mode) (push m modes)))) `(not ,@modes))
    – npostavs
    Feb 13 '18 at 2:53
  • Nice idea, but I don't think it's going to deal with autoloads?
    – phils
    Feb 13 '18 at 3:57

Looking at whitespace.el I see we could also do this:

(with-eval-after-load 'whitespace
  (setq whitespace-enable-predicate
        `(lambda ()
           (and (funcall ,whitespace-enable-predicate)
                (not (derived-mode-p 'magit-mode))))))

This is somewhat similar to @JulianKniephoff's answer, but not using advice. However I note that advice is somewhat expected in this case, as C-h v whitespace-enable-predicate states:

This variable is normally modified via ‘add-function’.

  • add-function isn't advice, it's just a fancier way of doing that kind of variable setting (e.g., a particular advantage for this case is that the add-function form is idempotent).
    – npostavs
    Feb 13 '18 at 12:57
  • I'm siding with the add-function docstring :)
    – phils
    Feb 13 '18 at 14:05
  • Hah. I would change the docstring, but I'm not sure what word to use instead of "advice" there (Bug#25581 is kind of related).
    – npostavs
    Feb 13 '18 at 23:52

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.