Fix race condition to ensure concurrent MRs successfully merged via merge train when checks pass

Summary

The direct "Merge" button is displayed, rather than the "Set to auto-merge", and/or some merge requests are being processed as direct merges, despite merge train being configured. Upon reviewing logs, the following common errors were detected.

  1. PG::UniqueViolation on index_merge_trains_on_merge_request_id - Race condition causing duplicate key constraint violations
  2. NoMethodError for undefined sha method - Nil reference error when accessing diff_head_pipeline.sha

Steps to reproduce

  1. Enable Pipelines must succeed, Skipped pipelines are considered Successful and All threads must be resolved for the project
  2. Configure merge train on project
  3. Ensure the pipeline is deleted or fails to be created before the auto-merge service executes
  4. Create a merge request to auto-merge when checks pass
  5. Trigger multiple concurrent requests to add the merge request to the merge train (e.g., using parallel API calls or rapid UI interactions)

What is the current bug behavior?

  • Merge requests intermittently bypass merge train and process as direct merges
  • auto_merge_strategy shows null instead of "merge_train"
  • merge_user shows null
  • 8+ seconds later button changes to merge train
  • Database constraint violations occur
  • Pipeline appears to be missing (nil) during merge train execution

What is the expected correct behavior?

  • The merge request should be successfully added to the merge train if configured
  • All concurrent requests should complete without errors
  • The auto-merge should be enabled even if the pipeline is missing
  • No excessive delays in merge processing

Relevant logs and/or screenshots

Error 1: PG::UniqueViolation Error Evidence

PG::UniqueViolation: ERROR: duplicate key value violates unique constraint "index_merge_trains_on_merge_request_id"
  DETAIL:  Key (merge_request_id)=(12345) already exists.

Error 2: NoMethodError Evidence

NoMethodError: undefined method `sha' for nil:NilClass
  at /ee/app/services/auto_merge/add_to_merge_train_when_checks_pass_service.rb:XX:in `execute'
Edited Jan 06, 2026 by Ket Slaats
Assignee Loading
Time tracking Loading