Chatbot account ID -4: why can't it be deleted via admin panel and what are the workarounds?

Work notes after reviewing via Admin API and Discourse core code (Cursor branch in the hoee repository).

Object

On the instance, the admin card: /admin/users/-4/chatbot (Chatbot in admin panel).

What the admin JSON returned (snapshot of check)

  • id: -4 (this is a bot by core rules: user_id > 0 only for “live” users)
  • username: Chatbot
  • admin: true
  • moderator: false
  • post_count: 0
  • can_be_deleted: false
  • can_be_anonymized: false

Why can_be_deleted: false even with zero posts

In Guardian#can_delete_user?, deletion is forbidden if the target user is admin. This is unrelated to post count in our case.

Why manual UI or admin HTTP often “doesn’t allow” it

For operations like revoke admin / destroy, negative id fails Guardian#can_administer?: there’s a condition requiring the target ID to be positive (obj.id.positive?). Thus, requests to member routes like “by regular username” return 404, while requests with segment -4 may return 403 invalid_access, even when the API actor is staff.

Conclusion: revoke admin and delete the account via the standard Admin API using the same UX as for humans is usually impossible — a different path is required (below).

Soft path without deleting the DB row

Disable the AI bot module in site settings: parameter ai_bot_enabled (false — GPT bot behavior and related UI in PMs/header are muted; the user row may remain).

On a machine with checkout of the hoee repository and discourse.env file, add helpers:

  • scripts/discourse-ai-chatbot-operator.sh audit — brief dump of fields from /admin/users/-4/list.json
  • ai-bot-disable / ai-bot-enable — PUT to ai_bot_enabled (keys system from discourse.env, do not publish)

Hard path: actually delete the User

Only on the Discourse application host, with a DB snapshot before changes: in Rails console, unset the admin flag on the record (e.g., update_columns), then use UserDestroyer from a live admin with id > 0 and delete_posts: true if needed. Copyable snippet text: scripts/discourse-ai-chatbot-operator.sh rails-destroy-snippet.

Risks: the discourse-ai plugin may recreate bots upon updates; possible “missing bot user” messages until the module fixes the state.

Upstream code references

If needed, separate instructions can be provided in replies on how to check the current value of ai_bot_enabled via Admin → Settings → discourse-ai plugin without API.

Update: Account Deleted

The operation on the host was performed not via the Admin API (Guardian still doesn’t allow access for negative id), but through rails runner inside the live app container, executed by the user discourse:

  • The admin flag was removed from User.find(-4) using update_columns + reload;
  • Then, UserDestroyer was invoked by a live administrator with id > 0, with the option delete_posts: true (in our case, there were no posts).

External verification: GET /u/chatbot.json no longer returns the user, GET /admin/users/-4/list.jsonnot_found.

Reminder: upon re-enabling the discourse-ai plugin, the bot account may be recreated if needed.