Attempt to recreate deleted chat channel with the same name (still) fails

Continuing the discussion from Attempt to recreate deleted chat channel with same name fails:

This bug was reported in the linked thread but seems to still persist for me. I’m on latest and did a git pull and launcher rebuild yesterday.

When trying to name a new chat channel after any previously used chat channel name, there is a 500 error in the JS console.

In the Discourse error logs I get

Failed to handle exception in exception app middleware : ActiveRecord::RecordNotUnique : PG::UniqueViolation: ERROR:  duplicate key value violates unique constraint "index_chat_channels_on_slug"
DETAIL:  Key (slug)=(sec-fhir) already exists.

In the Rails console I can see that the deleted ChatChannels have gone, but I suspect somewhere the deleted slug remains in an index or in some other DB dependency and hasn’t been deleted.

This workaround doesn’t work for me, upon trying to rename “foo2” to “foo” I get the same 500 error, because of the failed uniqueness constraint on the slug.

I’m not sure how to safely delete the (indexed?) slugs of deleted ChatChannels, but I’d be willing to have a go.


Possibly related: this issue which also affects slugs, but it doesn’t seem to be the same issue: Attempt to recreate deleted chat channel with same name fails

2 Likes

I just tested the following now and had no issue:

  1. Create channel with name “whiskers” and slug “whiskers”
  2. Delete channel
  3. Create channel with name “whiskers” and slug “whiskers”

That worked.

When the channel is deleted (step 2), the slug is automatically changed to something unique. But since you deleted your channel prior to that change being introduced, the old slug may be still hanging around.

You can probably manually update the slug for the deleted channel via the rails console, but I’m not sure what the right incantation is. I’ll ask around.

Note also, that channel slugs are now able to be edited independently of the channel name, so as a workaround, you could also make a channel with the desired name today and choose a different slug that doesn’t conflict.

2 Likes

This is super unexpected.

We don’t delete channels, we only soft delete them. So they should still be here with the deleted_at column filled.

If you run this in your console, you get no results?

ChatChannel.find_by(slug: "sec-fhir")
[1] pry(main)> ChatChannel.find_by(slug: "sec-fhir")
=> nil

I can confirm that this test also works for me on my instance, which is fully up to date.

I think the issue is that somewhere in the DB there is some slug hanging around that should have been deleted, which wasn’t, maybe there was a bug in a previous version which is now fixed. Chat has only been enabled on this instance for 17 days, so any bug would have to have been active in that time-frame.

1 Like

Can’t repro this in any way. After doing a DB backup maybe you can try these in the rails console. Seems surprising though.

[1] pry(main)> DB.exec("DROP INDEX IF EXISTS index_chat_channels_on_slug;")
[2] pry(main)> DB.exec("CREATE UNIQUE INDEX index_chat_channels_on_slug ON chat_channels(slug);")

I checked and this is actually expected, since we exclude records with deleted_at filled in even with find_by:

ChatChannel.find_by(slug: "sec-fhir")
  ChatChannel Load (0.4ms)  SELECT "chat_channels".* FROM "chat_channels" WHERE "chat_channels"."deleted_at" IS NULL AND "chat_channels"."slug" = 'sec-fhir' LIMIT 1
=> nil

You will need to do this instead (adding with_deleted):

ChatChannel.with_deleted.find_by(slug: "sec-fhir")
  ChatChannel Load (0.3ms)  SELECT "chat_channels".* FROM "chat_channels" WHERE "chat_channels"."slug" = 'sec-fhir' LIMIT 1
=> #<CategoryChannel:0x00007fc9bfb4abf0
 id: 124,
 chatable_id: 19,
 deleted_at: Wed, 15 Feb 2023 01:19:20.982181000 UTC +00:00,
 deleted_by_id: nil,
 featured_in_category_id: nil,
 delete_after_seconds: nil,
 chatable_type: "Category",
 created_at: Fri, 13 Jan 2023 01:46:43.730329000 UTC +00:00,
 updated_at: Wed, 15 Feb 2023 01:19:56.427647000 UTC +00:00,
 name: "test channel",
 description: "",
 status: "archived",
 user_count: 1,
 last_message_sent_at: Fri, 13 Jan 2023 01:46:51.130903000 UTC +00:00,
 auto_join_users: false,
 user_count_stale: false,
 slug: "sec-fhir",
 type: "CategoryChannel",
 allow_channel_wide_mentions: true,
 messages_count: 0,
 threading_enabled: false>

So to clear out the old deleted channel slug do something like this:

channel = ChatChannel.with_deleted.find_by(slug: "sec-fhir")
channel.update!(slug: "#{channel.deleted_at.strftime("%Y%m%d-%H%M")}-#{channel.slug}-deleted")

Maybe we need a migration to fix these @mcwumbly and @joffreyjaffeux ?

2 Likes

Oh yes right forgot the with_deleted in this case :+1:

I suggest we just let your answer here for now. Should be a rare case: deleted before fix + wants to re-create with same name.

4 Likes

Thanks for the above. I didn’t know about with_deleted but that enabled me to see the deleted instances and to rename their slugs as per your snippet.

I can confirm this is fixed. I would agree with @joffreyjaffeux that this is not likely to be affecting many users so I’d say it’s enough that a Rails console fix is here in the thread.

3 Likes

Excellent, good to hear that resolved it for you Marcus. Closing off this topic now.

2 Likes

When I try to create a new channel (named “general”, same for the slug) the following error shows up in the logs (nothing is happening on frontend).

No “Closed” channels are shown.

I might have had a general channel in the past - and probably deleted it (is it default?)

Can not repro with another random slug (create > delete > create works just fine).

Failed to handle exception in exception app middleware : ActiveRecord::RecordNotUnique : PG::UniqueViolation: ERROR:  duplicate key value violates unique constraint "index_chat_channels_on_slug"
DETAIL:  Key (slug)=(general) already exists.

I’ve slipped your post over to here to keep the reports grouped together. :+1:

Would the workaround above be suitable in your case as well?

The workaround in OP, no didn’t work.

This also didn’t seem to work for me.

[1] pry(main)> ChatChannel.find_by(slug: "general")
NameError: uninitialized constant ChatChannel
from (pry):1:in `__pry__'

The workaround for the OPs issue is in this post:

2 Likes

I tried these, that is what my shared code block was about.

I failed to run these commands in rails.

Maybe I’m doing something wrong here?

EDIT: to be clear, the suggested workaround turns the same error when looking for the channel

[7] pry(main)> ChatChannel.with_deleted.find_by(slug: "general")
NameError: uninitialized constant ChatChannel
from (pry):7:in `__pry__'
2 Likes

Alright, I managed to solve the issue (at least, I think so).

For me it was kind of a hassle to figure this all out so I’ll share the full steps.

cd /var/discourse && ./launcher enter app
rails c
DB.exec("UPDATE chat_channels SET slug = 'new' WHERE slug = 'old';")

So in your rails console this will look like this:

[1] pry(main)> DB.exec("UPDATE chat_channels SET slug = 'new' WHERE slug = 'old';")
=> 1
[2] pry(main)> exit
root@discourse-app:~# exit
logout
➜  discourse git:(main) ✗ 

I am now able to create a new channel with the wanted slug.

Is this the (or a) right way?

2 Likes

The workaround failing above is due to some namespacing we introduced weeks ago. ChatChannel is now Chat::Channel

1 Like

I was expecting something like that but was not able to find it. I hope my DB change is a good workaround as well? So far no problems.

2 Likes