Unable to add Topic that results in the same slug as an existing topic
Summary
Unable to add an additional topic when the same slug is generated
Steps to reproduce
- Create a new project
- Add a topic like
bx::code::c(this can be done via the UI or API). - Use the PUT projects/:id REST API to add a topic such as
bx::code::c++to the project. They key here is to use something that will generate the same slug (e.g.bxcodec)
Example Project
Not Applicable
What is the current bug behavior?
The topic is not added and the project is not updated. If using the WebUI you get a generic error. If using the REST API you get a 200 OK with an empty response.
The concern with the 200 OK has been logged in #548609
What is the expected correct behavior?
GitLab detects the condition,generates a unique slug, adds the Topic and Project::Topic
Additional Troubleshooting
If you change the slug on the existing Topic e.g. bxcodec to bxcodex the new topic can be added.
Relevant logs and/or screenshots
There are no logs that are generated when this problem occurs, which is a problem on its own. However, with DEBUG logging enabled after it queries the database for the slug it stops.
gitlab-rails/production.log
Projects::ProjectTopic Delete All (0.9ms) /*application:web,correlation_id:01JXWYXY62FGSTMNM1111CANG0,endpoint_id:PUT /api/:version/projects/:id,db_config_database:gitlabhq_production,db_config_name:main*/ DELETE FROM "project_topics" WHERE ("project_topics"."id") IN (SELECT "project_topics"."id" FROM "project_topics" WHERE "project_topics"."project_id" = 2 AND "project_topics"."topic_id" = 2 ORDER BY "project_topics"."id" ASC) Projects::Topic Update All (2.6ms) /*application:web,correlation_id:01JXWYXY62FGSTMNM1111CANG0,endpoint_id:PUT /api/:version/projects/:id,db_config_database:gitlabhq_production,db_config_name:main*/ UPDATE "topics" SET "total_projects_count" = COALESCE("total_projects_count", 0) - 1 WHERE "topics"."id" = 2 Projects::Topic Load (0.7ms) /*application:web,correlation_id:01JXWYXY62FGSTMNM1111CANG0,endpoint_id:PUT /api/:version/projects/:id,db_config_database:gitlabhq_production,db_config_name:main*/ SELECT "topics".* FROM "topics" WHERE "topics"."organization_id" = 1 AND (lower(name) = 'bx::code::c++') ORDER BY "topics"."total_projects_count" DESC LIMIT 1 Projects::Topic Exists? (0.7ms) /*application:web,correlation_id:01JXWYXY62FGSTMNM1111CANG0,endpoint_id:PUT /api/:version/projects/:id,db_config_database:gitlabhq_production,db_config_name:main*/ SELECT 1 AS one FROM "topics" WHERE LOWER("topics"."name") = LOWER('bx::code::c++') AND "topics"."organization_id" = 1 LIMIT 1 Projects::Topic Exists? (0.6ms) /*application:web,correlation_id:01JXWYXY62FGSTMNM1111CANG0,endpoint_id:PUT /api/:version/projects/:id,db_config_database:gitlabhq_production,db_config_name:main*/ SELECT 1 AS one FROM "topics" WHERE LOWER("topics"."slug") = LOWER('bxcodec') AND "topics"."organization_id" = 1 LIMIT 1 Namespace Load (1.5ms) /*application:web,correlation_id:01JXWYXY62FGSTMNM1111CANG0,endpoint_id:PUT /api/:version/projects/:id,db_config_database:gitlabhq_production,db_config_name:main*/ SELECT "namespaces"."id", "namespaces"."name", "namespaces"."path", "namespaces"."owner_id", "namespaces"."created_at", "namespaces"."updated_at", "namespaces"."type", "namespaces"."description", "namespaces"."avatar", "namespaces"."membership_lock", "namespaces"."share_with_group_lock", "namespaces"."visibility_level", "namespaces"."request_access_enabled", "namespaces"."ldap_sync_status", "namespaces"."ldap_sync_error", "namespaces"."ldap_sync_last_update_at", "namespaces"."ldap_sync_last_successful_update_at", "namespaces"."ldap_sync_last_sync_at", "namespaces"."description_html", "namespaces"."lfs_enabled", "namespaces"."parent_id", "namespaces"."shared_runners_minutes_limit", "namespaces"."repository_size_limit", "namespaces"."require_two_factor_authentication", "namespaces"."two_factor_grace_period", "namespaces"."cached_markdown_version", "namespaces"."project_creation_level", "namespaces"."runners_token", "namespaces"."file_template_project_id", "namespaces"."saml_discovery_token", "namespaces"."runners_token_encrypted", "namespaces"."custom_project_templates_group_id", "namespaces"."auto_devops_enabled", "namespaces"."extra_shared_runners_minutes_limit", "namespaces"."last_ci_minutes_notification_at", "namespaces"."last_ci_minutes_usage_notification_level", "namespaces"."subgroup_creation_level", "namespaces"."max_pages_size", "namespaces"."max_artifacts_size", "namespaces"."mentions_disabled", "namespaces"."default_branch_protection", "namespaces"."max_personal_access_token_lifetime", "namespaces"."push_rule_id", "namespaces"."shared_runners_enabled", "namespaces"."allow_descendants_override_disabled_shared_runners", "namespaces"."traversal_ids", "namespaces"."organization_id" FROM "namespaces" WHERE "namespaces"."owner_id" = 2 AND "namespaces"."type" = 'User' LIMIT 1 User Update (3.3ms) /*application:web,correlation_id:01JXWYXY62FGSTMNM1111CANG0,endpoint_id:PUT /api/:version/projects/:id,db_config_database:gitlabhq_production,db_config_name:main*/ UPDATE "users" SET "updated_at" = '2025-06-16 18:09:55.054527', "last_activity_on" = '2025-06-16' WHERE "users"."id" = 2
Output of checks
This bug happens on GitLab.com
Results of GitLab environment info
Expand for output related to GitLab environment info
System information
System: Ubuntu 20.04
Proxy: no
Current User: git
Using RVM: no
Ruby Version: 3.2.5
Gem Version: 3.6.7
Bundler Version:2.6.5
Rake Version: 13.0.6
Redis Version: 7.2.7
Sidekiq Version:7.3.9
Go Version: unknown
GitLab information
Version: 18.0.1-ee
Revision: 3426be1b938
Directory: /opt/gitlab/embedded/service/gitlab-rails
DB Adapter: PostgreSQL
DB Version: 16.8
URL: https://gitlab.example.com
HTTP Clone URL: https://gitlab.example.com/some-group/some-project.git
SSH Clone URL: git@gitlab.example.com:some-group/some-project.git
Elasticsearch: no
Geo: no
Using LDAP: no
Using Omniauth: yes
Omniauth Providers:
GitLab Shell
Version: 14.42.0
Repository storages:
default: unix:/var/opt/gitlab/gitaly/gitaly.socket
GitLab Shell path: /opt/gitlab/embedded/service/gitlab-shell
Gitaly
default Address: unix:/var/opt/gitlab/gitaly/gitaly.socket
default Version: 18.0.1
default Git Version: 2.49.0.gl2
Possible fixes
https://gitlab.com/gitlab-org/gitlab/-/blame/master/app/models/projects/topic.rb?ref_type=heads#L20
/cc @ulisesf