# 404 on earned badge event when badge is disabled

**URL:** <https://meta.discourse.org/t/404-on-earned-badge-event-when-badge-is-disabled/46486>\
**Category:** Bug\
**Created:** [2016年六月27日 00:16 UTC](https://meta.discourse.org/t/404-on-earned-badge-event-when-badge-is-disabled/46486 "2016-06-27T00:16:15Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![gvanrossum](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/gvanrossum/32/121694_2.png) [@gvanrossum](https://meta.discourse.org/u/gvanrossum)\
**Post date:** [2016年六月27日 00:16 UTC](https://meta.discourse.org/t/404-on-earned-badge-event-when-badge-is-disabled/46486/1 "2016-06-27T00:16:15Z")

</div>

A few of us created a [new Discourse instance](https://discuss.python.org) 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:

- [Discussions on Python.org](https://discuss.python.org/badges/5/welcome?username=guido)

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.”)

---

<div class="post-metadata">

**Author:** ![sam](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/sam/32/102149_2.png) [@sam](https://meta.discourse.org/u/sam)\
**Post date:** [2016年六月27日 04:51 UTC](https://meta.discourse.org/t/404-on-earned-badge-event-when-badge-is-disabled/46486/2 "2016-06-27T04:51:45Z")

</div>

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:

```plaintext
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.

---

<div class="post-metadata">

**Author:** ![gvanrossum](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/gvanrossum/32/121694_2.png) [@gvanrossum](https://meta.discourse.org/u/gvanrossum)\
**Post date:** [2016年六月27日 15:57 UTC](https://meta.discourse.org/t/404-on-earned-badge-event-when-badge-is-disabled/46486/3 "2016-06-27T15:57:23Z")

</div>

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  
disabled.”)

---

<div class="post-metadata">

**Author:** ![Moin](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/moin/32/554653_2.png) [@Moin](https://meta.discourse.org/u/Moin)\
**Post date:** [2026年一月7日 09:33 UTC](https://meta.discourse.org/t/404-on-earned-badge-event-when-badge-is-disabled/46486/4 "2026-01-07T09:33:03Z")

</div>

> [@Remove notifications for disabled badges](https://meta.discourse.org/t/remove-notifications-for-disabled-badges/392572/5):
>
> Fixed in

---

<div class="post-metadata">

**Author:** ![tgxworld](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/tgxworld/32/106117_2.png) [@tgxworld](https://meta.discourse.org/u/tgxworld)\
**Post date:** [2026年一月8日 00:21 UTC](https://meta.discourse.org/t/404-on-earned-badge-event-when-badge-is-disabled/46486/5 "2026-01-08T00:21:15Z")

</div>


