404 on earned badge event when badge is disabled

A few of us created a new Discourse instance and started using it for a bit. Then we decided to disable most badges. By then I had already earned some of the disabled badges. The badge events stuck around in my personal “recents” list (the dropdown under my user icon) but when I clicked on them I got a 404 from our server. You may still be able to try this; this is an example:

IMO those events should be removed from my “recents” list (what do you call that thing?) or they should have told me something like “this badge has been disabled”.

(UPDATE: So maybe it’s not exactly a 404, but the response showed a “:(” icon with text “Page Not Found” and “Oops, the application tried to load a URL that doesn’t exist.” When you click on it from here you get a different but similar response: “Oops! That page doesn’t exist or is private.”)


Yes, I agree this is not ideal.

Our notifications table stores information about the “reason” in a text column containing json. This happens because there are a wide range of reasons you could be getting a notification and creating a big pile of columns would widen the table a lot and decrease flexibility around notifications.

We keep topic and post number, but there is a range of other types of ids (like group mentions, invites, badges and so on)

The “lookup my notifications” query needs to stay super fast, I did not want to force joins into 5 or so tables just to determine if the source is legit. (we do ensure post notifications are legit though - deleting a topic hides the related notifications)

Historically, people don’t go about disabling badges beyond the first few weeks of running a forum. So in practice this is a very minor issue.

That said there are 2 options you have here:

  • In practice nobody ever looks beyond the first 20 or so notifications, this issue will drown in a few days of active use.

  • If it is really bugging you you can clean up the old notifications from the table:

cd /var/discourse
./launcher enter app
rails c
% Notification.where('notification_type=12 AND data like \'%"badge_id":5,%\'').destroy_all

(5 is the badge id for welcome, destroy_all calls object model so it will live refresh all browsers)

On our side there are a couple of things I would like to clean up.

  1. Our “client side” 404 should look exactly like the server side 404, reloading a 404 page should always result in the same 404

  2. We should optionally be allowed to send in a bit more information into the 404 pages. As it stands we do a raise Discourse::NotFound we should allow raise Discourse::NotFound, "Badge is no longer enabled" and float that info into the 404.


Thanks! Or perhaps disabling a badge should be implemented differently, and
disabling should just stop awarding badges and displaying them in lists
that query for them, but still allow the badge page (like the one I
mentioned) to be hit. (Maybe adding a note “this badge has since been