This bug has been around for a long time. I researched it last year, and here are the steps to reproduce it:
- As an admin, set
max favorite badges
to 2, and create at least one badge that can be earned multiple times. - As a regular user, set two badges as favorites, one of which is the badge that can be earned multiple times (referred to as Badge A).
- As an admin, grant the user Badge A again.
- As a regular user, refresh the page and try to un-star Badge A. You will encounter the error.
The reason for the error is that each time a badge that can be earned multiple times is granted, a new user_badge
record is created in the database. However, when the user has favorited the badge and then receives it again, the new user_badge
record is not automatically marked as is_favorite
. When the user tries to un-star Badge A, the frontend sends the most recent user_badge
ID by default. Since this record is not marked as is_favorite
, the backend assumes the user is trying to set a new badge as a favorite (instead of un-favoriting it), which exceeds the max favorite badges
limit, resulting in the error.
The relevant code is located at:
One possible solution is to modify line 131 to:
if UserBadge.where(badge: user_badge.badge, user: user_badge.user).pluck(:is_favorite).any? &&
However, this doesn’t fully address the inconsistency in the database records.
As a temporary workaround, a regular user can un-favorite all badges by running the following JavaScript code in the console:
const user_name = require("discourse/models/user").default.current().username;
const badges = await require("discourse/models/user-badge").default.findByUsername(user_name);
const favorites = new Map();
badges.filter((b)=>b.is_favorite).forEach((b)=>favorites.set(b.badge_id,b));
favorites.forEach((b)=>b.favorite());