9

When there's an error in one of my init files, I get a vague message like this when I launch Emacs:

Warning (initialization): An error occurred while loading /Users/im/.emacs.d/init.elc:
(wrong-type-argument listp helm-find-files-actions)

It doesn't tell me which of my many configuration files contains the error, or which line. Searching my files doesn't help because, guess what, the function helm-find-files-actions doesn't actually appear in any of my init files. To track down the offending line of code, I have to do $ emacs --debug-init.

Is there no way to get Emacs to automatically tell me where the offending line is without having to quit and run $ emacs --debug-init? I know I can bisect + eval the files manually but that's even slower. It would be so much better if, when there's an error in one of my init files, Emacs could:

  1. tell me which init file
  2. tell me the line number that contains the error
  3. ideally, open that init file and take me to the offending line

Is this possible with Emacs, or am I living in a fantasy world?

incandescentman
  • 4,111
  • 16
  • 53
  • 5
    How about enable debugging (without relaunching) by evaluating `(setq debug-on-error t)` and then evaluate your `init.el` again -- e.g., open it up and type `M-x eval-buffer`. – lawlist Jul 10 '15 at 04:46
  • 2
    This seems to be a recurring problem in Lisp implementations with the notable exception of [Racket](http://docs.racket-lang.org/guide/stx-obj.html) which has taken care of adding support for source locations. I have pulled off [a small hack to display line numbers in backtraces](http://emacs.stackexchange.com/a/7854/10), perhaps that helps. – wasamasa Jul 10 '15 at 08:29
  • 1
    Perhaps a separate question, but I wonder if there's a way to enable `debug-init` automatically for the next start whenever your init file changes... – glucas Jul 10 '15 at 12:37
  • 2
    @glucas In that case, my emacs will always start with `--debug-init` :) – Kaushal Modi Jul 10 '15 at 15:05
  • Is there a reason not to always launch Emacs with `--debug-init` by default? – incandescentman Jul 15 '15 at 18:42

3 Answers3

3

I know I can bisect + eval the files manually but that's even slower.

Wrong! So I will ignore the "without relaunching" part of your question title.

This is common and classic, as is the solution: binary search. If turning on debug-on-error and using option --debug-init doesn't help, then do this:

Bisect your init file recursively, to locate the tiny bit of it that is responsible for the problem.

That's all. Binary search is very quick, powerful, and simple. People too often avoid it, thinking that they can think their way through the problem quicker.

To bisect your init file recursively:

  1. Comment out half of it. You can use M-x comment-region to comment out the region of selected text. (You can uncomment the region using C-u with the same command. (For convenience, you can bind comment-region to a key.)

  2. Start Emacs. Did you see the same problem? If yes, then the problem is not caused by the part you commented out. If no, then it is.

  3. For the problematic part: Comment out the other part and half of the problematic part.

Repeat #2 and #3, over and over. It doesn't take long: 1/2, 3/4, 7/8, 15/16, 31/32, 63/64, 127/128, 255/256, 511/512, 1023/1024,...

It doesn't matter how big your init file is or how much other code it loads (if the problem is in other code then repeat the same process on that file, etc.).

If fact, the bigger the pile of code you are trying to search, the more binary search helps you.

Drew
  • 75,699
  • 9
  • 109
  • 225
  • 1
    Exactly. Say searching 100 takes 1 minute. With binary search, 100,000 lines should only take, at most, another minute. (Give or take) – PythonNut Jul 16 '15 at 05:40
  • I feel like the poster asked three questions and this answers none of them while also being the most up voted answer, which doesn't make sense. – Hercislife May 16 '23 at 12:49
2

Simple answer: Just open your init.el file and do a M-x eval-buffer. I do this all the time to debug init files

bpaul
  • 123
  • 4
1

You could simply load your init file up in a buffer and C-x C-e to evaluate each s-expression and figure out which one blows up.

I know that's not ideal but if you're dead set against restarting it's what I'd do.

feoh
  • 900
  • 1
  • 6
  • 9