Users stuck on a redirect loop after transferring project
Summary
https://gitlab.zendesk.com/agent/tickets/85028
https://sentry.gitlap.com/gitlab/gitlabcom/issues/110697/
I've been unsuccessful in trying to reproduce on test instance, but able to reproduce consistently in user's project. Attempting to rename user's project from a subgroup to the root group results in an ERR_TOO_MANY_REDIRECTS
in the original namespace and an empty project in the new namespace. Old namespace is also listed in the user's projects.
Steps to reproduce
- User moves
group/archive/website
togroup/website
- Transfer results in an error, once
group/archive/website
is reloaded it results inERR_TOO_MANY_REDIRECTS
, new empty project appears ingroup/website
.
User Project
https://gitlab.com/group/archive/website/edit
What is the current bug behavior?
When transferring a project from one namespace to another it fails midway, creating an empty project with no repository and making the project inaccessible. Original namespace is then redirected to the same original namespace. If I destroy the new route for group/website
, project becomes accessible in group/archive/website
and no longer redirects.
Relevant logs and/or screenshots
irb(main):011:0> ::Projects::TransferService.new(project, user).execute(group)
(3.1ms) SELECT COUNT(DISTINCT "members"."id") FROM "members" LEFT OUTER JOIN "users" ON "members"."user_id" = "users"."id" WHERE "members"."type" IN ('GroupMember') AND "members"."source_type" = 'Namespace' AND "users"."state" = 'active' AND "members"."requested_at" IS NULL AND "members"."source_id" IN (WITH RECURSIVE "base_and_ancestors" AS (SELECT "namespaces".* FROM "namespaces" WHERE "namespaces"."type" IN ('Group') AND "namespaces"."id" = 2152523
UNION
SELECT "namespaces".* FROM "namespaces", "base_and_ancestors" WHERE "namespaces"."type" IN ('Group') AND "namespaces"."id" = "base_and_ancestors"."parent_id") SELECT "id" FROM "base_and_ancestors" AS "namespaces") AND (("members"."user_id" IS NULL AND "members"."invite_token" IS NOT NULL) OR "users"."state" = 'active') AND "members"."requested_at" IS NULL AND "members"."access_level" = 50 AND "members"."user_id" = 1144873 [["source_type", "Namespace"], ["state", "active"], ["access_level", 50]]
GroupMember Load (1.8ms) SELECT "members".* FROM "members" LEFT OUTER JOIN "users" ON "members"."user_id" = "users"."id" WHERE "members"."type" IN ('GroupMember') AND "members"."source_type" = 'Namespace' AND "users"."state" = 'active' AND "members"."requested_at" IS NULL AND "members"."source_id" = 1655168 AND "members"."user_id" = 1144873 ORDER BY "members"."access_level" DESC LIMIT 1 [["source_type", "Namespace"], ["state", "active"], ["source_id", 1655168]]
Project Exists (1.1ms) SELECT 1 AS one FROM "projects" WHERE "projects"."path" = 'website' AND "projects"."namespace_id" = 1655168 LIMIT 1 [["path", "website"], ["namespace_id", 1655168]]
(1.1ms) BEGIN
(0.7ms) SELECT "features"."key" FROM "features"
Feature::FlipperGate Load (0.8ms) SELECT "feature_gates".* FROM "feature_gates" WHERE "feature_gates"."feature_key" = 'gitaly_repository_exists' [["feature_key", "gitaly_repository_exists"]]
Feature::FlipperGate Load (0.7ms) SELECT "feature_gates".* FROM "feature_gates" WHERE "feature_gates"."feature_key" = 'gitaly_repository_exists' [["feature_key", "gitaly_repository_exists"]]
Group Load (1.4ms) SELECT "namespaces".* FROM "namespaces" WHERE "namespaces"."type" IN ('Group') AND "namespaces"."id" = 1655168 AND "namespaces"."type" IN ('Group') AND "namespaces"."type" = 'Group' LIMIT 1 [["id", 1655168], ["type", "Group"]]
Route Exists (1.0ms) SELECT 1 AS one FROM "routes" WHERE (LOWER("routes"."path") = LOWER('group/website') AND "routes"."id" != 6428875) LIMIT 1
Route Exists (0.7ms) SELECT 1 AS one FROM "routes" WHERE (LOWER("routes"."path") = LOWER('group/website') AND "routes"."id" != 6428875) LIMIT 1
Project Exists (0.9ms) SELECT 1 AS one FROM "projects" WHERE ("projects"."path" = 'website' AND "projects"."id" != 3853683 AND "projects"."namespace_id" = 1655168) LIMIT 1
Project Exists (0.9ms) SELECT 1 AS one FROM "projects" WHERE ("projects"."name" = 'website' AND "projects"."id" != 3853683 AND "projects"."namespace_id" = 1655168) LIMIT 1
Project Exists (0.7ms) SELECT 1 AS one FROM "projects" WHERE "projects"."namespace_id" = 1655168 AND "projects"."path" = 'website.wiki' LIMIT 1 [["namespace_id", 1655168], ["path", "website.wiki"]]
Project Load (1.6ms) SELECT "projects".* FROM "projects" INNER JOIN "routes" ON "routes"."source_id" = "projects"."id" AND "routes"."source_type" = 'Project' WHERE "projects"."pending_delete" = 't' AND ((LOWER(routes.path) = LOWER('group/website'))) ORDER BY (CASE WHEN routes.path = 'group/website' THEN 0 ELSE 1 END) LIMIT 1 [["source_type", "Project"], ["pending_delete", true]]
(0.6ms) ROLLBACK
gitlab-shell failed with error 1:
gitlab-shell failed with error 1:
Group Load (1.0ms) SELECT "namespaces".* FROM "namespaces" WHERE "namespaces"."type" IN ('Group') AND "namespaces"."id" = 2152523 AND "namespaces"."type" IN ('Group') AND "namespaces"."type" = 'Group' LIMIT 1 [["id", 2152523], ["type", "Group"]]
(0.6ms) BEGIN
Route Exists (0.8ms) SELECT 1 AS one FROM "routes" WHERE (LOWER("routes"."path") = LOWER('group/website') AND "routes"."id" != 6428875) LIMIT 1
Route Exists (1.3ms) SELECT 1 AS one FROM "routes" WHERE (LOWER("routes"."path") = LOWER('group/website') AND "routes"."id" != 6428875) LIMIT 1
Project Exists (0.9ms) SELECT 1 AS one FROM "projects" WHERE ("projects"."path" = 'website' AND "projects"."id" != 3853683 AND "projects"."namespace_id" = 2152523) LIMIT 1
Project Exists (0.8ms) SELECT 1 AS one FROM "projects" WHERE ("projects"."name" = 'website' AND "projects"."id" != 3853683 AND "projects"."namespace_id" = 2152523) LIMIT 1
Project Exists (0.8ms) SELECT 1 AS one FROM "projects" WHERE "projects"."namespace_id" = 2152523 AND "projects"."path" = 'website.wiki' LIMIT 1 [["namespace_id", 2152523], ["path", "website.wiki"]]
(0.5ms) COMMIT
License Load (0.9ms) SELECT "licenses".* FROM "licenses" ORDER BY "licenses"."id" DESC LIMIT 1
(2.7ms) SELECT "members"."user_id" FROM "members" LEFT OUTER JOIN "users" ON "members"."user_id" = "users"."id" WHERE "members"."type" IN ('GroupMember') AND "members"."source_type" = 'Namespace' AND "users"."state" = 'active' AND "members"."requested_at" IS NULL AND "members"."source_id" IN (WITH RECURSIVE "base_and_ancestors" AS (SELECT "namespaces".* FROM "namespaces" WHERE "namespaces"."type" IN ('Group') AND "namespaces"."id" = 2152523
UNION
SELECT "namespaces".* FROM "namespaces", "base_and_ancestors" WHERE "namespaces"."type" IN ('Group') AND "namespaces"."id" = "base_and_ancestors"."parent_id") SELECT "id" FROM "base_and_ancestors" AS "namespaces") [["source_type", "Namespace"], ["state", "active"]]
(4.0ms) SELECT "members"."user_id" FROM "members" LEFT OUTER JOIN "users" ON "members"."user_id" = "users"."id" WHERE "members"."type" IN ('GroupMember') AND "members"."source_type" = 'Namespace' AND "users"."state" = 'active' AND "members"."requested_at" IS NULL AND "members"."source_id" = 1655168 [["source_type", "Namespace"], ["state", "active"], ["source_id", 1655168]]
License Load (1.0ms) SELECT "licenses".* FROM "licenses" ORDER BY "licenses"."id" DESC LIMIT 1
(0.8ms) SELECT pg_current_xlog_insert_location()::text AS location
License Load (1.1ms) SELECT "licenses".* FROM "licenses" ORDER BY "licenses"."id" DESC LIMIT 1
(0.7ms) SELECT pg_current_xlog_insert_location()::text AS location
License Load (0.9ms) SELECT "licenses".* FROM "licenses" ORDER BY "licenses"."id" DESC LIMIT 1
(0.8ms) SELECT pg_current_xlog_insert_location()::text AS location
License Load (1.6ms) SELECT "licenses".* FROM "licenses" ORDER BY "licenses"."id" DESC LIMIT 1
(0.8ms) SELECT pg_current_xlog_insert_location()::text AS location
License Load (0.9ms) SELECT "licenses".* FROM "licenses" ORDER BY "licenses"."id" DESC LIMIT 1
(0.7ms) SELECT pg_current_xlog_insert_location()::text AS location
License Load (0.8ms) SELECT "licenses".* FROM "licenses" ORDER BY "licenses"."id" DESC LIMIT 1
(0.6ms) SELECT pg_current_xlog_insert_location()::text AS location
License Load (0.9ms) SELECT "licenses".* FROM "licenses" ORDER BY "licenses"."id" DESC LIMIT 1
(0.6ms) SELECT pg_current_xlog_insert_location()::text AS location
License Load (0.9ms) SELECT "licenses".* FROM "licenses" ORDER BY "licenses"."id" DESC LIMIT 1
(0.7ms) SELECT pg_current_xlog_insert_location()::text AS location
License Load (0.8ms) SELECT "licenses".* FROM "licenses" ORDER BY "licenses"."id" DESC LIMIT 1
(1.0ms) SELECT pg_current_xlog_insert_location()::text AS location
License Load (1.3ms) SELECT "licenses".* FROM "licenses" ORDER BY "licenses"."id" DESC LIMIT 1
(0.6ms) SELECT pg_current_xlog_insert_location()::text AS location
ActiveRecord::RecordInvalid: Validation failed: Name has already been taken
from /opt/gitlab/embedded/lib/ruby/gems/2.3.0/gems/activerecord-4.2.8/lib/active_record/validations.rb:79:in `raise_record_invalid'
from /opt/gitlab/embedded/lib/ruby/gems/2.3.0/gems/activerecord-4.2.8/lib/active_record/validations.rb:43:in `save!'
from /opt/gitlab/embedded/lib/ruby/gems/2.3.0/gems/activerecord-4.2.8/lib/active_record/attribute_methods/dirty.rb:29:in `save!'
from /opt/gitlab/embedded/lib/ruby/gems/2.3.0/gems/activerecord-4.2.8/lib/active_record/transactions.rb:291:in `block in save!'
from /opt/gitlab/embedded/lib/ruby/gems/2.3.0/gems/activerecord-4.2.8/lib/active_record/transactions.rb:351:in `block in with_transaction_returning_status'
from /opt/gitlab/embedded/lib/ruby/gems/2.3.0/gems/activerecord-4.2.8/lib/active_record/connection_adapters/abstract/database_statements.rb:211:in `transaction'
from /opt/gitlab/embedded/service/gitlab-rails/lib/gitlab/database/load_balancing/connection_proxy.rb:77:in `block in write_using_load_balancer'
from /opt/gitlab/embedded/service/gitlab-rails/lib/gitlab/database/load_balancing/load_balancer.rb:66:in `block in read_write'
from /opt/gitlab/embedded/service/gitlab-rails/lib/gitlab/database/load_balancing/load_balancer.rb:116:in `retry_with_backoff'
from /opt/gitlab/embedded/service/gitlab-rails/lib/gitlab/database/load_balancing/load_balancer.rb:65:in `read_write'
from /opt/gitlab/embedded/service/gitlab-rails/lib/gitlab/database/load_balancing/connection_proxy.rb:71:in `write_using_load_balancer'
from /opt/gitlab/embedded/service/gitlab-rails/lib/gitlab/database/load_balancing/connection_proxy.rb:45:in `block (2 levels) in <class:ConnectionProxy>'
from /opt/gitlab/embedded/lib/ruby/gems/2.3.0/gems/activerecord-4.2.8/lib/active_record/transactions.rb:220:in `transaction'
from /opt/gitlab/embedded/lib/ruby/gems/2.3.0/gems/activerecord-4.2.8/lib/active_record/transactions.rb:348:in `with_transaction_returning_status'
from /opt/gitlab/embedded/lib/ruby/gems/2.3.0/gems/activerecord-4.2.8/lib/active_record/transactions.rb:291:in `save!'
from /opt/gitlab/embedded/lib/ruby/gems/2.3.0/gems/state_machines-activerecord-0.4.0/lib/state_machines/integrations/active_record.rb:505:in `block in save!'
.
Also reported in https://gitlab.zendesk.com/agent/tickets/86152