I have dig into our codebase and looks like the error is kinda simple, but I would like to verify my assumptions.
We have a site setting named slug_generation_method which must be changed from the default ascii value to encoded in order to trigger this bug. When you change this site setting, we clear all slugs and generate those again.
What I don’t understand is why when the site setting is set to “encoded” we generate a slug like this:
[3] pry(main)> SiteSetting.slug_generation_method
=> "encoded"
[4] pry(main)> Slug.for(t.slug)
=> "キノの旅-home-thread-intermediate-book-club"
where I expected that “encoded” means something like
[5] pry(main)> CGI.escape(Slug.for(t.slug))
=> "%E3%82%AD%E3%83%8E%E3%81%AE%E6%97%85-home-thread-intermediate-book-club"
This appears to come from
https://github.com/discourse/discourse/pull/3370
The raw slug from the table is returned in the Location header 301 response when a topic slug doesn’t match, and IMO we should return a valid URL in there.