# Approval button on user's profile doesn't work

**URL:** https://meta.discourse.org/t/approval-button-on-users-profile-doesnt-work/403620
**Category:** Bug
**Created:** [May 22, 2026, 11:52am UTC](https://meta.discourse.org/t/approval-button-on-users-profile-doesnt-work/403620 "2026-05-22T11:52:01Z")
**Posts on this page:** 12
**Page:** 1

<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: [May 22, 2026, 11:52am UTC](https://meta.discourse.org/t/approval-button-on-users-profile-doesnt-work/403620/1 "2026-05-22T11:52:01Z")

</div>

Continuing the discussion from [Notification claims X users for approval, but none are found](https://meta.discourse.org/t/notification-claims-x-users-for-approval-but-none-are-found/262853/17):

I recently enabled `require_approval` on my forum again. And right after that I got notifications about a user waiting for approval but when I click the link in the message the is no user in the review queue. Since then I received it every 7 days. So I used [data explorer](https://meta.discourse.org/t/32566?silent=true) to find the user who wasn’t approved but doesn’t appear in the review queue.

> **more detailed steps quoted from the other topic**
>
> > [@Notification claims X users for approval, but none are found](https://meta.discourse.org/t/notification-claims-x-users-for-approval-but-none-are-found/262853/17):
> >
> > You can use a [data explorer](https://meta.discourse.org/t/32566?silent=true) query to find the user you don’t see in the queue and approve them directly on their admin page.
> > 
> > ```plaintext
> > SELECT id as user_id
> > FROM users
> > WHERE approved = false
> > AND active = true
> > 
> > ```
> > 
> > This is what I did recently. I also get this message every 7 days. So I used the query and this was the result
> > 
> > ![Screenshot20260522091428Firefox](https://global.discourse-cdn.com/meta/original/4X/1/d/6/1d6de29f2a345f2ce5d45372ce498ab6147e6432.jpeg)
> > 
> > And I verified it in the users admin page
> > 
> > ![Screenshot20260522085849Firefox](https://global.discourse-cdn.com/meta/original/4X/7/4/6/746538d48b59e8a6ab5151d5c6b8d2d4cc986b44.jpeg)
> > 
> > But I still have to find out why the button doesn’t work in my case. I haven’t had a chance to look at it yet.

So when I look at the users admin page, there is the expected approve button. THe problem is that it doesn’t work. There is no visible feedback like a modal showing an error. But there is one in my browser console

> **Error in the browser console**
>
> ```plaintext
> ajax.js:233 PUT https://my-forum.discourse.group/admin/users/123/approve 500 (Internal Server Error)
> send @ jquery.js:9940
> ajax @ jquery.js:9521
> performAjax @ ajax.js:233
> (anonymous) @ ajax.js:246
> approve @ admin-user.js:220
> approve @ index.js:224
> (anonymous) @ d-button.gjs:206
> invoke @ index.js:264
> flush @ index.js:180
> flush @ index.js:334
> _end @ index.js:762
> end @ index.js:565
> _runExpiredTimers @ index.js:869
> setTimeout
> setTimeout @ index.js:39
> _installTimerTimeout @ index.js:912
> _reinstallTimerTimeout @ index.js:896
> _later @ index.js:829
> later @ index.js:652
> next @ index.js:562
> _triggerAction @ d-button.gjs:203
> click @ d-button.gjs:161
> 
> /admin/users/123/anon84265489:1 Uncaught (in promise) {jqXHR: {…}, textStatus: 'error', errorThrown: ''}errorThrown: ""jqXHR: abort: ƒ (e)always: ƒ ()catch: ƒ (e)done: ƒ ()fail: ƒ ()getAllResponseHeaders: ƒ ()getResponseHeader: ƒ (e)jqTextStatus: "error"overrideMimeType: ƒ (e)pipe: ƒ ()progress: ƒ ()promise: ƒ (e)readyState: 4requestedUrl: "/admin/users/123/approve"responseText: "<!DOCTYPE html>\n<html>\n<head>\n <title>Oops - Error 500</title>\n <meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\">\n</head>\n<body>\n <h1>Oops</h1>\n <p>The software powering this discussion forum encountered an unexpected problem. We apologize for the inconvenience.</p>\n <p>Detailed information about the error was logged, and an automatic notification generated. We'll take a look at it.</p>\n <p>No further action is necessary. However, if the error condition persists, you can provide additional detail, including steps to reproduce the error, by posting a discussion topic in the site's feedback category.</p>\n</body>\n</html>\n"setRequestHeader: ƒ (e,t)state: ƒ ()status: 500statusCode: ƒ (e)statusText: "error"then: ƒ (e,i,n)[[Prototype]]: ObjecttextStatus: "error"[[Prototype]]: Object
> Promise.then
> approve @ admin-user.js:222
> approve @ index.js:224
> (anonymous) @ d-button.gjs:206
> invoke @ index.js:264
> flush @ index.js:180
> flush @ index.js:334
> _end @ index.js:762
> end @ index.js:565
> _runExpiredTimers @ index.js:869
> setTimeout
> setTimeout @ index.js:39
> _installTimerTimeout @ index.js:912
> _reinstallTimerTimeout @ index.js:896
> _later @ index.js:829
> later @ index.js:652
> next @ index.js:562
> _triggerAction @ d-button.gjs:203
> click @ d-button.gjs:161
> 
> ```

So next I checked /logs:

> **Error in /logs**
>
> ```plaintext
> Message (14 copies reported)
> 
> Reviewable::InvalidAction (Can't perform `approve_user` on ReviewableUser)
> app/models/reviewable.rb:860:in 'Reviewable#validate_action!'
> app/models/reviewable.rb:360:in 'Reviewable#perform'
> app/controllers/admin/users_controller.rb:306:in 'Admin::UsersController#approve'
> app/controllers/application_controller.rb:452:in 'block in ApplicationController#with_resolved_locale'
> app/controllers/application_controller.rb:452:in 'ApplicationController#with_resolved_locale'
> app/controllers/application_controller.rb:1101:in 'ApplicationController#ensure_dont_cache_page'
> lib/middleware/omniauth_bypass_middleware.rb:35:in 'Middleware::OmniauthBypassMiddleware#call'
> lib/middleware/crawler_hooks.rb:13:in 'Middleware::CrawlerHooks#call'
> lib/content_security_policy/middleware.rb:12:in 'ContentSecurityPolicy::Middleware#call'
> lib/middleware/anonymous_cache.rb:417:in 'Middleware::AnonymousCache#call'
> lib/middleware/csp_script_nonce_injector.rb:12:in 'Middleware::CspScriptNonceInjector#call'
> lib/middleware/track_view_session_id_injector.rb:12:in 'Middleware::TrackViewSessionIdInjector#call'
> config/initializers/008-rack-cors.rb:26:in 'Discourse::Cors#call'
> lib/middleware/default_headers.rb:13:in 'Middleware::DefaultHeaders#call'
> config/initializers/100-quiet_logger.rb:20:in 'DiscourseRackQuietAssetsLogger#call'
> config/initializers/100-silence_logger.rb:29:in 'SilenceLogger#call'
> lib/middleware/enforce_hostname.rb:23:in 'Middleware::EnforceHostname#call'
> lib/middleware/request_tracker.rb:372:in 'Middleware::RequestTracker#call'
> lib/middleware/overload_protections.rb:18:in 'Middleware::OverloadProtections#call'
> lib/middleware/processing_request.rb:14:in 'Middleware::ProcessingRequest#call'
> 
> Backtrace
> 
> app/models/reviewable.rb:860:in 'Reviewable#validate_action!'
> app/models/reviewable.rb:360:in 'Reviewable#perform'
> app/controllers/admin/users_controller.rb:306:in 'Admin::UsersController#approve'
> actionpack (8.0.5) lib/action_controller/metal/basic_implicit_render.rb:8:in 'ActionController::BasicImplicitRender#send_action'
> actionpack (8.0.5) lib/abstract_controller/base.rb:215:in 'AbstractController::Base#process_action'
> actionpack (8.0.5) lib/action_controller/metal/rendering.rb:193:in 'ActionController::Rendering#process_action'
> actionpack (8.0.5) lib/abstract_controller/callbacks.rb:261:in 'block in AbstractController::Callbacks#process_action'
> activesupport (8.0.5) lib/active_support/callbacks.rb:120:in 'block in ActiveSupport::Callbacks#run_callbacks'
> app/controllers/application_controller.rb:452:in 'block in ApplicationController#with_resolved_locale'
> i18n (1.14.8) lib/i18n.rb:354:in 'I18n::Base#with_locale'
> app/controllers/application_controller.rb:452:in 'ApplicationController#with_resolved_locale'
> activesupport (8.0.5) lib/active_support/callbacks.rb:129:in 'block in ActiveSupport::Callbacks#run_callbacks'
> app/controllers/application_controller.rb:1101:in 'ApplicationController#ensure_dont_cache_page'
> activesupport (8.0.5) lib/active_support/callbacks.rb:129:in 'block in ActiveSupport::Callbacks#run_callbacks'
> activesupport (8.0.5) lib/active_support/callbacks.rb:140:in 'ActiveSupport::Callbacks#run_callbacks'
> actionpack (8.0.5) lib/abstract_controller/callbacks.rb:260:in 'AbstractController::Callbacks#process_action'
> actionpack (8.0.5) lib/action_controller/metal/rescue.rb:27:in 'ActionController::Rescue#process_action'
> actionpack (8.0.5) lib/action_controller/metal/instrumentation.rb:76:in 'block in ActionController::Instrumentation#process_action'
> activesupport (8.0.5) lib/active_support/notifications.rb:210:in 'block in ActiveSupport::Notifications.instrument'
> activesupport (8.0.5) lib/active_support/notifications/instrumenter.rb:58:in 'ActiveSupport::Notifications::Instrumenter#instrument'
> activesupport (8.0.5) lib/active_support/notifications.rb:210:in 'ActiveSupport::Notifications.instrument'
> actionpack (8.0.5) lib/action_controller/metal/instrumentation.rb:75:in 'ActionController::Instrumentation#process_action'
> actionpack (8.0.5) lib/action_controller/metal/params_wrapper.rb:259:in 'ActionController::ParamsWrapper#process_action'
> activerecord (8.0.5) lib/active_record/railties/controller_runtime.rb:39:in 'ActiveRecord::Railties::ControllerRuntime#process_action'
> actionpack (8.0.5) lib/abstract_controller/base.rb:152:in 'AbstractController::Base#process'
> actionview (8.0.5) lib/action_view/rendering.rb:40:in 'ActionView::Rendering#process'
> rack-mini-profiler (4.0.1) lib/mini_profiler/profiling_methods.rb:90:in 'block in ActionController::Base#profile_method'
> actionpack (8.0.5) lib/action_controller/metal.rb:252:in 'ActionController::Metal#dispatch'
> actionpack (8.0.5) lib/action_controller/metal.rb:335:in 'ActionController::Metal.dispatch'
> actionpack (8.0.5) lib/action_dispatch/routing/route_set.rb:67:in 'ActionDispatch::Routing::RouteSet::Dispatcher#dispatch'
> actionpack (8.0.5) lib/action_dispatch/routing/route_set.rb:50:in 'ActionDispatch::Routing::RouteSet::Dispatcher#serve'
> actionpack (8.0.5) lib/action_dispatch/routing/mapper.rb:32:in 'block in <class:Constraints>'
> actionpack (8.0.5) lib/action_dispatch/routing/mapper.rb:62:in 'ActionDispatch::Routing::Mapper::Constraints#serve'
> actionpack (8.0.5) lib/action_dispatch/journey/router.rb:53:in 'block in ActionDispatch::Journey::Router#serve'
> actionpack (8.0.5) lib/action_dispatch/journey/router.rb:133:in 'block in ActionDispatch::Journey::Router#find_routes'
> actionpack (8.0.5) lib/action_dispatch/journey/router.rb:126:in 'Array#each'
> actionpack (8.0.5) lib/action_dispatch/journey/router.rb:126:in 'ActionDispatch::Journey::Router#find_routes'
> actionpack (8.0.5) lib/action_dispatch/journey/router.rb:34:in 'ActionDispatch::Journey::Router#serve'
> actionpack (8.0.5) lib/action_dispatch/routing/route_set.rb:908:in 'ActionDispatch::Routing::RouteSet#call'
> lib/middleware/omniauth_bypass_middleware.rb:35:in 'Middleware::OmniauthBypassMiddleware#call'
> lib/middleware/crawler_hooks.rb:13:in 'Middleware::CrawlerHooks#call'
> rack (2.2.23) lib/rack/tempfile_reaper.rb:15:in 'Rack::TempfileReaper#call'
> rack (2.2.23) lib/rack/conditional_get.rb:40:in 'Rack::ConditionalGet#call'
> rack (2.2.23) lib/rack/head.rb:12:in 'Rack::Head#call'
> actionpack (8.0.5) lib/action_dispatch/http/permissions_policy.rb:38:in 'ActionDispatch::PermissionsPolicy::Middleware#call'
> lib/content_security_policy/middleware.rb:12:in 'ContentSecurityPolicy::Middleware#call'
> lib/middleware/anonymous_cache.rb:417:in 'Middleware::AnonymousCache#call'
> lib/middleware/csp_script_nonce_injector.rb:12:in 'Middleware::CspScriptNonceInjector#call'
> lib/middleware/track_view_session_id_injector.rb:12:in 'Middleware::TrackViewSessionIdInjector#call'
> config/initializers/008-rack-cors.rb:26:in 'Discourse::Cors#call'
> rack (2.2.23) lib/rack/session/abstract/id.rb:266:in 'Rack::Session::Abstract::Persisted#context'
> rack (2.2.23) lib/rack/session/abstract/id.rb:260:in 'Rack::Session::Abstract::Persisted#call'
> actionpack (8.0.5) lib/action_dispatch/middleware/cookies.rb:706:in 'ActionDispatch::Cookies#call'
> actionpack (8.0.5) lib/action_dispatch/middleware/callbacks.rb:31:in 'block in ActionDispatch::Callbacks#call'
> activesupport (8.0.5) lib/active_support/callbacks.rb:100:in 'ActiveSupport::Callbacks#run_callbacks'
> actionpack (8.0.5) lib/action_dispatch/middleware/callbacks.rb:30:in 'ActionDispatch::Callbacks#call'
> actionpack (8.0.5) lib/action_dispatch/middleware/debug_exceptions.rb:31:in 'ActionDispatch::DebugExceptions#call'
> actionpack (8.0.5) lib/action_dispatch/middleware/show_exceptions.rb:32:in 'ActionDispatch::ShowExceptions#call'
> logster (2.21.0) lib/logster/middleware/reporter.rb:40:in 'Logster::Middleware::Reporter#call'
> lib/middleware/default_headers.rb:13:in 'Middleware::DefaultHeaders#call'
> lograge (0.14.0) lib/lograge/rails_ext/rack/logger.rb:18:in 'Rails::Rack::Logger#call_app'
> railties (8.0.5) lib/rails/rack/logger.rb:29:in 'Rails::Rack::Logger#call'
> config/initializers/100-quiet_logger.rb:20:in 'DiscourseRackQuietAssetsLogger#call'
> config/initializers/100-silence_logger.rb:29:in 'SilenceLogger#call'
> actionpack (8.0.5) lib/action_dispatch/middleware/request_id.rb:34:in 'ActionDispatch::RequestId#call'
> lib/middleware/enforce_hostname.rb:23:in 'Middleware::EnforceHostname#call'
> rack (2.2.23) lib/rack/method_override.rb:24:in 'Rack::MethodOverride#call'
> rack (2.2.23) lib/rack/sendfile.rb:127:in 'Rack::Sendfile#call'
> plugins/discourse-prometheus/lib/middleware/metrics.rb:14:in 'DiscoursePrometheus::Middleware::Metrics#call'
> rack-mini-profiler (4.0.1) lib/mini_profiler.rb:191:in 'Rack::MiniProfiler#call'
> message_bus (4.5.2) lib/message_bus/rack/middleware.rb:60:in 'MessageBus::Rack::Middleware#call'
> lib/middleware/request_tracker.rb:372:in 'Middleware::RequestTracker#call'
> actionpack (8.0.5) lib/action_dispatch/middleware/remote_ip.rb:96:in 'ActionDispatch::RemoteIp#call'
> lib/middleware/overload_protections.rb:18:in 'Middleware::OverloadProtections#call'
> lib/middleware/processing_request.rb:14:in 'Middleware::ProcessingRequest#call'
> rails_failover (2.3.0) lib/rails_failover/active_record/middleware.rb:67:in 'block in RailsFailover::ActiveRecord::Middleware#call'
> activerecord (8.0.5) lib/active_record/connection_handling.rb:401:in 'ActiveRecord::ConnectionHandling#with_role_and_shard'
> activerecord (8.0.5) lib/active_record/connection_handling.rb:149:in 'ActiveRecord::ConnectionHandling#connected_to'
> rails_failover (2.3.0) lib/rails_failover/active_record/middleware.rb:64:in 'RailsFailover::ActiveRecord::Middleware#call'
> rails_multisite (7.0.0) lib/rails_multisite/middleware.rb:26:in 'RailsMultisite::Middleware#call'
> railties (8.0.5) lib/rails/engine.rb:535:in 'Rails::Engine#call'
> railties (8.0.5) lib/rails/railtie.rb:226:in 'Kernel#public_send'
> railties (8.0
> 
> Env
> 
> HTTP HOSTS: my-forum.discourse.group
> 
> ```

I am not sure what causes this. THere are other anonymized users who were apprved just fine when I enabled the setting

---

<div class="post-metadata">

### Author: ![Ed\_S](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/ed_s/32/134015_2.png) [@Ed\_S](https://meta.discourse.org/u/Ed_S)
#### Post date: [May 22, 2026, 12:10pm UTC](https://meta.discourse.org/t/approval-button-on-users-profile-doesnt-work/403620/2 "2026-05-22T12:10:07Z")

</div>

That’s a “me too” from me, too.

(Edit: I discovered exactly one user in this state, active a few weeks ago, not anonymised)

---

<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: [May 22, 2026, 1:14pm UTC](https://meta.discourse.org/t/approval-button-on-users-profile-doesnt-work/403620/3 "2026-05-22T13:14:04Z")

</div>

Your “me too” is very helpful as a confirmation that the fact that my user has been anonymized is not the reason for this bug.

[Data explorer](https://meta.discourse.org/t/32566?silent=true) says the user is reviewable by moderator

| user\_id | id | type | target\_id | target\_type | reviewable\_by\_moderator |
| --- | --- | --- | --- | --- | --- |
| anon84265489 | 264 | ReviewableUser | 123 | User | true |

> **query**
>
> ```sql
> SELECT 
> u.id AS user_id,
> r.id,
> r.type,
> r.target_id,
> r.target_type,
> r.reviewable_by_moderator
> FROM reviewables r
> JOIN users u
> ON r.target_id = u.id
> WHERE u.approved = false
> AND u.active = true
> 
> ```

---

<div class="post-metadata">

### Author: ![Ed\_S](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/ed_s/32/134015_2.png) [@Ed\_S](https://meta.discourse.org/u/Ed_S)
#### Post date: [May 22, 2026, 9:00pm UTC](https://meta.discourse.org/t/approval-button-on-users-profile-doesnt-work/403620/4 "2026-05-22T21:00:57Z")

</div>

I don’t understand how this is malfunctioning, but I can at least find some of the bits of code which are concluding this action can’t be done. But I don’t see why they conclude that. I suppose [line 859 in reviewable.rb](https://github.com/discourse/discourse/blob/main/app/models/reviewable.rb#L859) has the logic.

approve() has line 306 in users\_controller.rb

> <https://github.com/discourse/discourse/blob/main/app/controllers/admin/users_controller.rb#L299C1-L309C1>

perform() has line 360 in reviewable.rb

> <https://github.com/discourse/discourse/blob/main/app/models/reviewable.rb#L353-L360>

validate\_action!() has line 860 in reviewable.rb which raises the exception

> <https://github.com/discourse/discourse/blob/main/app/models/reviewable.rb#L852-L862>

---

<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: [May 22, 2026, 9:30pm UTC](https://meta.discourse.org/t/approval-button-on-users-profile-doesnt-work/403620/5 "2026-05-22T21:30:40Z")

</div>

I think the problem might be that the user has been reviewed before. I am not sure it’s possible to review the same user again. So far I haven’t been able to reproduce this.

I still wasn’t able to reproduce this. But I found out that the user who doesn’t appear in the review queue had been flagged as `suspect_user` after they signed up in December. At that time `must_approve_users` was disabled on my forum. So I acted on them back then. I am not sure if `disagreed` means I selected to keep the user. But when I tried to reproduce now the only other option was to delete the user. Not sure how `status = 2` happened.  
When I enabled `must_approve_users` a few weeks ago, the user was not automatically approved because there was a reviewable with the user\_id as the target\_id. That makes sense.

But I still have no clue how I ended up with a user I didn’t approve, but also didn’t delete when they were flagged.

| reviewable | status | status | reason | context | created\_at |
| --- | --- | --- | --- | --- | --- |
| 264 | disagreed | 2 | suspect\_user | NULL | 2025-12-18T14:16:28.322Z |

> **query**
>
> ```sql
> SELECT
> rs.reviewable_id,
> CASE
> WHEN rs.status = 0 THEN 'pending'
> WHEN rs.status = 1 THEN 'agreed'
> WHEN rs.status = 2 THEN 'disagreed'
> WHEN rs.status = 3 THEN 'ignored'
> END as status,
> rs.status as status_id,
> rs.reason,
> rs.context,
> rs.created_at
> FROM reviewable_scores rs
> JOIN reviewables r
> ON rs.reviewable_id = r.id
> JOIN users u
> ON r.target_id = u.id
> WHERE u.approved = false
> AND u.active = true
> 
> ```

---

<div class="post-metadata">

### Author: ![Ed\_S](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/ed_s/32/134015_2.png) [@Ed\_S](https://meta.discourse.org/u/Ed_S)
#### Post date: [May 23, 2026, 5:59am UTC](https://meta.discourse.org/t/approval-button-on-users-profile-doesnt-work/403620/6 "2026-05-23T05:59:53Z")

</div>

Good find - looks like the same is true for me - a user (in my case a live and active user until a couple of weeks ago) who had in the distant past acquired a suspect\_user status.

 ![image](https://global.discourse-cdn.com/meta/original/4X/8/f/f/8ff0ad49b350b90cfb5581d162209e278d34810b.png)

I think this user has probably found themselves unable to use the forum since I switched on the approval of new users.  
Joined Apr 9, 2021 Last Post Apr 16 Seen Apr 16 Views 1311 Trust Level member  
Stats 78 days visited 4h read time 3m recent read time 83 topics viewed  
491 posts read 6 given 31 received 4 topics created 25 posts created

Wading back through my review queue, I see no items on that date, and no items with that username.

Edit: very odd, that suspect\_user date is some 9 or 10 days before the user’s join date.

---

<div class="post-metadata">

### Author: ![Ed\_S](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/ed_s/32/134015_2.png) [@Ed\_S](https://meta.discourse.org/u/Ed_S)
#### Post date: [May 23, 2026, 6:27am UTC](https://meta.discourse.org/t/approval-button-on-users-profile-doesnt-work/403620/7 "2026-05-23T06:27:00Z")

</div>

I see now that in my case we got a spam user, picked up the ID 332, was flagged and deleted. A few days later, we got a new user, who again picked up the ID 332.

Knowing the user ID of the affected valid user, I ran this [Data Explorer](https://meta.discourse.org/t/32566?silent=true) query:

```plaintext
SELECT *
FROM reviewables
WHERE target_id = 332
ORDER BY created_at DESC

```

Edit: and according to ask.discourse this shouldn’t happen. But I can say we’ve never interfered in the database. We have migrated and so I suppose that’s a restore operation, but at that time (March 2021) we had never migrated.

I think this may be a repro of a closed previous observation:  
[Deleted user info shows up in new user approval](https://meta.discourse.org/t/deleted-user-info-shows-up-in-new-user-approval/161720)

---

<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: [May 24, 2026, 10:12am UTC](https://meta.discourse.org/t/approval-button-on-users-profile-doesnt-work/403620/8 "2026-05-24T10:12:36Z")

</div>

I don’t think this is the case in my case. The reviewable was created after the user:

From `reviewables`:

| id | type | status | target | target\_type | created\_at | updated\_at |
| --- | --- | --- | --- | --- | --- | --- |
| 264 | ReviewableUser | 2 | 123 | User | 2025-12-18T14:16:28.315Z | 2026-01-06T10:14:42.142Z |

From `users`:

| id | username | created\_at |
| --- | --- | --- |
| 123 | anon84265489 | 2025-12-15T11:31:28.666Z |

---

<div class="post-metadata">

### Author: ![Ed\_S](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/ed_s/32/134015_2.png) [@Ed\_S](https://meta.discourse.org/u/Ed_S)
#### Post date: [May 24, 2026, 1:04pm UTC](https://meta.discourse.org/t/approval-button-on-users-profile-doesnt-work/403620/9 "2026-05-24T13:04:53Z")

</div>

Does it look to you like a valid reviewable record but with the wrong target ID? That’s how mine looks.

It seems we can’t approve our users because the action of ‘approve’ is not an allowed action in this case. Perhaps there’s something about these specific problematic reviewable records which isn’t as it should be.

Possibly our unapproved users don’t show up in the review queue for the same reason.

I think there are several bugs here

- if approval button is going to raise an exception, the user should see why
- the review queue isn’t showing everything
- a bad reviewable record has appeared in our databases
- when we turned on account approvals, some number of our existing users were not automatically approved
- that failure was silent

---

<div class="post-metadata">

### Author: ![zogstrip](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/zogstrip/32/512781_2.png) [@zogstrip](https://meta.discourse.org/u/zogstrip)
#### Post date: [May 26, 2026, 1:37pm UTC](https://meta.discourse.org/t/approval-button-on-users-profile-doesnt-work/403620/10 "2026-05-26T13:37:39Z")

</div>

This will _hopefully_ catch a couple of the edge cases you’ve all raised in this topic 👍

> <https://github.com/discourse/discourse/pull/40303>
>
> Previously, clicking Approve on a user's admin profile 500'd with \`Reviewable::I…nvalidAction\` when that user had a non-pending \`ReviewableUser\` (e.g., after \`UserDestroyer.destroy\` was rescued because the user had posts), and toggling on \`must\_approve\_users\` also skipped those users — leaving them permanently un-approvable from the admin UI.
> 
> This change gates the \`:approve\_user\` action on \`guardian.can\_approve?(target)\` instead of \`status == "pending"\`, fixes the auto-approval initializer to only skip users with a \*pending\* reviewable, and centralizes \`updatable\_reviewable\_scores\` so re-approval correctly flips \`disagreed\` scores back to \`agreed\`.
> 
> https://meta.discourse.org/t/403620

---

<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: [May 26, 2026, 1:47pm UTC](https://meta.discourse.org/t/approval-button-on-users-profile-doesnt-work/403620/11 "2026-05-26T13:47:14Z")

</div>

Since you’re working on the `must_approve_users` section of `track-setting-changes` anyway, could you also add a check to ensure that not only is the `target_id` correct, but that the `target_type` is a user? That could prevent a [flagged chat message from preventing a user from being approved](https://meta.discourse.org/t/must-approve-users-notifications-are-incorrectly-triggered-by-old-users/240731/4).

---

<div class="post-metadata">

### Author: ![Ed\_S](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/ed_s/32/134015_2.png) [@Ed\_S](https://meta.discourse.org/u/Ed_S)
#### Post date: [September 1, 2026, 8:23am UTC](https://meta.discourse.org/t/approval-button-on-users-profile-doesnt-work/403620/12 "2026-09-01T08:23:37Z")

</div>

Having updated my forum a little while back to 2026.7.0, I see the approval button on the one troublesome account I have is now functioning, and I have approved the user.

I don’t believe we quite have a root cause for this situation, or any idea of how many accounts on other forums have become, and remain, silently unapproved.
