'FAILED' error when trying to un-star the 'Bug Reporter' badge

This bug has been around for a long time. I researched it last year, and here are the steps to reproduce it:

  1. As an admin, set max favorite badges to 2, and create at least one badge that can be earned multiple times.
  2. 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).
  3. As an admin, grant the user Badge A again.
  4. 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());
5 Likes