Fix: gate traversal_ids on commits in ES indexer behind AddTraversalIdsToCommits migration

Summary

The gitlab-elasticsearch-indexer (Go binary) unconditionally writes traversal_ids into commit documents when the field is provided via --traversal-ids. However, the commits index mapping does not have traversal_ids until the AddTraversalIdsToCommits migration (20260216152309) has finished. Because GitLab Advanced Search uses strict mapping, Elasticsearch/OpenSearch will reject any commit document that includes an unmapped field, causing indexing errors for all commits until the migration completes.

Additionally, a backfill migration (BackfillTraversalIdsOnCommits, 20260216153009) exists to populate traversal_ids on already-indexed commits after the mapping is in place — but this backfill is also not gated correctly.

Steps to reproduce

  1. Have an instance where AddTraversalIdsToCommits migration has not yet finished.
  2. Trigger any commit indexing (e.g. push to a repository with Advanced Search enabled).
  3. Observe errors from the Go indexer: Elasticsearch rejects the commit document due to traversal_ids not being present in the index mapping.

What is the current bug behavior?

ee/lib/gitlab/elastic/indexer.rb unconditionally passes --traversal-ids=<value> to the Go binary for all indexing calls. The Go binary then writes traversal_ids into every commit document. If the AddTraversalIdsToCommits mapping migration has not finished, Elasticsearch/OpenSearch rejects those documents with a mapping error.

Relevant code path:

  • build_command in ee/lib/gitlab/elastic/indexer.rb always appends --traversal-ids=...
  • submitCommit in internal/mode/advanced/indexer/indexer.go writes traversal_ids onto the commit body whenever the flag value is non-empty
  • The mapping migration 20260216152309_add_traversal_ids_to_commits.rb must complete before traversal_ids can be written to commit documents

What is the expected correct behavior?

The Go indexer should only write traversal_ids onto commit documents once the AddTraversalIdsToCommits mapping migration has finished.

The fix requires changes in two repositories:

gitlab-org/gitlab-elasticsearch-indexer

Add a new boolean CLI flag --commit-traversal-ids-enabled. When this flag is absent or false, the indexer must not set traversal_ids on commit documents (but should continue setting it on blobs and wiki blobs, where the mapping already exists).

gitlab-org/gitlab

In build_blob_specific_flags (or build_command) inside ee/lib/gitlab/elastic/indexer.rb, gate the --commit-traversal-ids-enabled flag behind:

migration_finished?(:add_traversal_ids_to_commits)

Only pass --commit-traversal-ids-enabled to the Go binary once that migration has completed.

Relevant logs and/or screenshots

Elasticsearch/OpenSearch error when strict mapping rejects an unmapped field:

{"type":"strict_dynamic_mapping_exception","reason":"mapping set to strict, dynamic introduction of [traversal_ids] within [_doc] is not allowed"}

Possible fixes

  • Add --commit-traversal-ids-enabled boolean flag to the Go indexer (internal/mode/advanced/advanced.go, threaded through elastic.Config, elastic.Client, and the Submitter interface)
  • Gate the flag in submitCommit (indexer.go) so traversal_ids is only added to commit bodies when the flag is true
  • In ee/lib/gitlab/elastic/indexer.rb, pass --commit-traversal-ids-enabled only when migration_finished?(:add_traversal_ids_to_commits) returns true