doomemacs / doomemacs/modules

mu4e module: bookmark duplicates on config reload

Open Beginner friendly
#78 0 comments 0 reactions 0 assignees View on GitHub
:email mu4e AI
Dominant language
Emacs Lisp
Stars
61
Forks
37
Avg merge
11h 19m
Merged PRs (30d)
7

Description

### Describe your issue

The `+mu4e` module's bookmark entry accumulates duplicates on every Doom config reload (`doom/reload` or `SPC h r r`). After N reloads, "Flagged messages" appears N+1 times in the bookmark list.

#### Root Cause

Format mismatch between Doom's `add-to-list` and mu4e 1.14's `mu4e-bookmarks` variable.

**mu4e 1.14** defines `mu4e-bookmarks` as a `defcustom` using **plist format**:

```elisp
(defcustom mu4e-bookmarks
'(( :name "Unread messages"
:query "flag:unread AND NOT flag:trashed"
:key ?u)
...)
```

**Doom's module** (`modules/email/mu4e/config.el:180`) adds the bookmark in **old 3-element list format**:

```elisp
(add-to-list 'mu4e-bookmarks
'("flag:flagged" "Flagged messages" ?f) t)
```

`add-to-list` uses `equal` for comparison. Since `("flag:flagged" "Flagged messages" ?f)` (old format) is not `equal` to `(:name "Flagged messages" :query "flag:flagged" :key ?f)` (plist format), `add-to-list` fails to detect the existing entry and appends a duplicate.

On each config reload:
1. mu4e reinitializes `mu4e-bookmarks` to its defcustom default (plist format, no "Flagged messages")
2. Doom's `after!` block runs `add-to-list` → adds "Flagged messages" in old format
3. This accumulates if the variable isn't fully reset between reloads

Additionally, `mu4e-bookmark-define` (mu4e 1.14's new API) cannot remove old-format entries because it compares keys with `(plist-get bm :key)`, which returns `nil` on old-format lists.

#### Affected Code

`modules/email/mu4e/config.el:180-181`:

```elisp
(add-to-list 'mu4e-bookmarks
'("flag:flagged" "Flagged messages" ?f) t)
```

#### Suggested Fix

Replace with `mu4e-bookmark-define` (mu4e 1.14+):

```elisp
(mu4e-bookmark-define "flag:flagged" "Flagged messages" ?f)
```

Or if backward compatibility with mu4e < 1.14 is needed:

```elisp
(if (fboundp 'mu4e-bookmark-define)
(mu4e-bookmark-define "flag:flagged" "Flagged messages" ?f)
(add-to-list 'mu4e-bookmarks
'("flag:flagged" "Flagged messages" ?f) t))
```

#### Workaround

Add deduplication after bookmark definitions in user config:

```elisp
(setq mu4e-bookmarks
(cl-delete-duplicates mu4e-bookmarks
:key (lambda (bm) (cond ((keywordp (car bm)) (plist-get bm :key))
((listp bm) (nth 2 bm))
(t nil)))
:test #'=))
```

Note: `(listp bm)` alone is insufficient — plists are also lists, so `(nth 2 bm)` on `(:name ... :query ... :key ?f)` returns the keyword `:query`, causing `(wrong-type-argument number-or-marker-p :query)` with `:test #'=`. The `(keywordp (car bm))` check distinguishes plist from old format.

### Steps to reproduce

1. Add custom Bookmark(s) to config.el
2. Sync/reload emacs configuration
3. Open mu4e

### System information

[doominfo.txt](https://github.com/user-attachments/files/31872733/doominfo.txt)

- mu4e 1.14.2-pre1 (built from source)

### Disclosures

- [x] This issue was written with/by AI.

Contributor guide

No contributing guide indexed for this repository

Research direction

Start at modules/email/mu4e/config.el:180-181 and compare the current add-to-list call with mu4e 1.14's mu4e-bookmark-define API. Reload the Doom configuration repeatedly, then open mu4e and verify that "Flagged messages" appears only once; preserve the fallback behavior if older mu4e versions must remain supported.

Written by the indexing model from the issue text.

Assessment

Tech stack
emacs-lisp
Domain
tooling
Issue type
Bug
Difficulty
2/5
Estimated time
1-3 hours
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
78/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.