Troubleshooting

In case you run into issues here are a few tips that can help you diagnose the problem.

Generally, it’s not a bad idea to configure Emacs to spit the backtrace on error (instead of just logging the error in the *Messages* buffer). You can toggle this behavior by using M-x toggle-debug-on-error.

Start with the doctor

Before you reach for the debugger, ask Projectile what it thinks is going on:

M-x projectile-doctor

(bound to s-p H, and available from the dispatch menu and the Projectile menu)

This opens a plain-text report in a *projectile-doctor* buffer describing the project around default-directory:

  • Project - the project root and, crucially, which entry of projectile-project-root-functions found it and off which marker file, the project name and where it came from, and whether the root is remote (TRAMP).

  • Type - the detected project type and the marker that matched, or an explanation of what to do when nothing matched.

  • Indexing - the indexing method, whether async indexing is on, the actual command Projectile will shell out to (ignore rules and all), and which of git, fd and rg are installed.

  • Files - how many files are indexed and how long a fresh index took, plus the cache state (cached or not, how old, when it expires, whether the cache is persistent).

  • Ignores - the dirconfig and its parsed + / - / ! entries, the effective ignore patterns, and which entries in the project root those patterns are hiding. Handy when files you expect to see are missing.

  • Findings - a short list of observations, each either ok or a concrete suggestion (fd not installed, caching off on a large project, a dirconfig using the deprecated prefix-less syntax, a remote project indexed synchronously, and so on).

Outside a project the report says so and lists the root functions that were tried, which is usually enough to figure out why a directory isn’t recognized.

The doctor is careful not to change what it measures: it never populates and never invalidates the file cache. When a project isn’t cached yet, the doctor indexes it with caching switched off and labels that as a fresh index, so running it can’t turn a cold project warm behind your back. On remote projects, indexing and program lookups are skipped rather than risking a hang, and the report marks them as skipped.

g regenerates the report, q buries it.

The report is plain, copy-pasteable text on purpose. When you file an issue on the issue tracker, pasting the output of projectile-doctor answers most of the questions we’d otherwise have to ask you.

Debugging Projectile commands

Emacs features a super powerful built-in Emacs Lisp debugger and using it is the best way to diagnose problems of any kind.

Here’s a great crash course on using the debugger.

To debug some command you need to do the following:

  • Figure out the name of the command you want to debug (e.g. by using C-h k to see which command is associated with some keybinding)

  • Find the source of the command (e.g. by using M-x find-function RET function-name)

  • Press C-u C-M-x while in the body of the function

  • Run the command again

At this point you’ll be dropped in the debugger and you can step forward until you find the problem.

Profiling Projectile commands

Emacs comes with a built-in profiler. Using it is pretty simple:

  1. Start it with M-x profiler-start.

  2. Invoke some commands.

  3. Get the report with M-x profiler-report.

If you intend to share the profiling results with someone it’s a good idea to save the report buffer to a file with C-x C-w.

Commonly encountered problems (and how to solve them)

Using some command causes Emacs to freeze for a while

Sometimes a Projectile command might hang for a while (e.g. due to a bug or a configuration issue). Such problems are super annoying, but are relatively easy to debug. Here are a few steps you can take in such situations:

  • Do M-x toggle-debug-on-quit

  • Reproduce the problem

  • Hit C-g around 10 seconds into the hang

This will bring up a backtrace with the entire function stack, including function arguments. So you should be able to figure out what’s going on (or at least what’s being required).

Projectile recognizes the wrong project

If Projectile does not think you are in a project, check how you expect Projectile to recognize the project: it needs the presence of an indicator file like .git or similar at the project root. If the directory you want to be a project is not version-controlled, a file named .projectile will do.

Note that Projectile caches the operation of checking which project (if any) a file belongs to. If you have already opened a file, then later added a marker file like .projectile, run M-x projectile-invalidate-cache to reset the cache.

M-x projectile-doctor tells you exactly which of the projectile-project-root-functions claimed the directory and off which marker file, which usually settles the "why this root?" question on the spot.

I upgraded Projectile using package.el and nothing changed

Emacs doesn’t load the new files, it only installs them on disk. To see the effect of changes you have to restart Emacs.

Some commands not working properly with the fish shell

I’m not sure what’s causing this (likely different quoting rules), but it’s easy to fix it:

(setq shell-file-name "/bin/bash")

In general, I’ve noticed that Emacs doesn’t play very well with fish.