ElasticIndexBulkCronWorker throwing NoMethodError for epics

Summary

Found while looking at the Advanced search dashboard in kibana.

There is a NoMethodError being thrown when epics are indexed into Elasticsearch

Steps to reproduce

Not confirmed, but I suspect this can be reproduced by indexing an epic with a group that does not have a root ancestor

What is the current bug behavior?

Indexing fails

What is the expected correct behavior?

Indexing should succeed

Relevant logs and/or screenshots

source image

Sentry error: https://new-sentry.gitlab.net/organizations/gitlab/issues/805533/?query=is:unresolved+ElasticIndexBulkCronWorker&statsPeriod=14d&stream_index=0

kibana search for error: https://log.gprd.gitlab.net/app/r/s/PZvS3

backtrace
[app/models/preloaders/group_root_ancestor_preloader.rb:20:in `block in execute', app/models/preloaders/group_root_ancestor_preloader.rb:19:in `each', app/models/preloaders/group_root_ancestor_preloader.rb:19:in `execute', ee/lib/elastic/latest/epic_class_proxy.rb:37:in `preload_indexing_data', ee/lib/elastic/multi_version_util.rb:76:in `preload_indexing_data', ee/app/models/concerns/elastic/application_versioned_search.rb:52:in `block (2 levels) in <module:ApplicationVersionedSearch>', activerecord (7.0.8.1) lib/active_record/relation.rb:435:in `instance_exec', activerecord (7.0.8.1) lib/active_record/relation.rb:435:in `block in _exec_scope', activerecord (7.0.8.1) lib/active_record/relation.rb:881:in `_scoping', activerecord (7.0.8.1) lib/active_record/relation.rb:435:in `_exec_scope', activerecord (7.0.8.1) lib/active_record/scoping/named.rb:175:in `block in scope', activerecord (7.0.8.1) lib/active_record/relation/delegation.rb:67:in `block in preload_indexing_data', activerecord (7.0.8.1) lib/active_record/relation.rb:881:in `_scoping', activerecord (7.0.8.1) lib/active_record/relation.rb:428:in `scoping', activerecord (7.0.8.1) lib/active_record/relation/delegation.rb:67:in `preload_indexing_data', ee/lib/gitlab/elastic/document_reference.rb:65:in `block in preload_indexing_data', ee/lib/gitlab/elastic/document_reference.rb:62:in `each', ee/lib/gitlab/elastic/document_reference.rb:62:in `preload_indexing_data', ee/lib/search/elastic/reference.rb:75:in `block (2 levels) in preload_database_records', ee/lib/search/elastic/reference.rb:74:in `each', ee/lib/search/elastic/reference.rb:74:in `each_slice', ee/lib/search/elastic/reference.rb:74:in `block in preload_database_records', ee/lib/search/elastic/reference.rb:73:in `each', ee/lib/search/elastic/reference.rb:73:in `preload_database_records', ee/app/services/elastic/process_bookkeeping_service.rb:186:in `execute_with_redis', ee/app/services/elastic/process_bookkeeping_service.rb:148:in `block in execute', lib/gitlab/redis/wrapper.rb:26:in `block in with', connection_pool (2.4.1) lib/connection_pool.rb:110:in `block (2 levels) in with', connection_pool (2.4.1) lib/connection_pool.rb:109:in `handle_interrupt', connection_pool (2.4.1) lib/connection_pool.rb:109:in `block in with', connection_pool (2.4.1) lib/connection_pool.rb:106:in `handle_interrupt', connection_pool (2.4.1) lib/connection_pool.rb:106:in `with', lib/gitlab/redis/wrapper.rb:26:in `with', ee/app/services/elastic/process_bookkeeping_service.rb:106:in `with_redis', ee/app/services/elastic/process_bookkeeping_service.rb:148:in `execute', ee/app/workers/concerns/elastic/bulk_cron_worker.rb:50:in `block in process_shard', lib/gitlab/exclusive_lease_helpers.rb:43:in `block in in_lock', lib/gitlab/exclusive_lease_helpers.rb:53:in `with_instrumentation', lib/gitlab/exclusive_lease_helpers.rb:42:in `in_lock', ee/app/workers/concerns/elastic/bulk_cron_worker.rb:49:in `process_shard', ee/app/workers/concerns/elastic/bulk_cron_worker.rb:34:in `perform', ee/app/workers/concerns/geo/skip_secondary.rb:14:in `perform', vendor/gems/sidekiq-7.1.6/lib/sidekiq/processor.rb:210:in `execute_job', vendor/gems/sidekiq-7.1.6/lib/sidekiq/processor.rb:180:in `block (4 levels) in process', vendor/gems/sidekiq-7.1.6/lib/sidekiq/middleware/chain.rb:180:in `traverse', vendor/gems/sidekiq-7.1.6/lib/sidekiq/middleware/chain.rb:183:in `block in traverse', lib/gitlab/sidekiq_middleware/skip_jobs.rb:51:in `call', vendor/gems/sidekiq-7.1.6/lib/sidekiq/middleware/chain.rb:182:in `traverse', vendor/gems/sidekiq-7.1.6/lib/sidekiq/middleware/chain.rb:183:in `block in traverse', lib/gitlab/database/load_balancing/sidekiq_server_middleware.rb:29:in `call', vendor/gems/sidekiq-7.1.6/lib/sidekiq/middleware/chain.rb:182:in `traverse', vendor/gems/sidekiq-7.1.6/lib/sidekiq/middleware/chain.rb:183:in `block in traverse', lib/gitlab/sidekiq_middleware/duplicate_jobs/strategies/until_executing.rb:16:in `perform', lib/gitlab/sidekiq_middleware/duplicate_jobs/duplicate_job.rb:44:in `perform', lib/gitlab/sidekiq_middleware/duplicate_jobs/server.rb:8:in `call', vendor/gems/sidekiq-7.1.6/lib/sidekiq/middleware/chain.rb:182:in `traverse', vendor/gems/sidekiq-7.1.6/lib/sidekiq/middleware/chain.rb:183:in `block in traverse', lib/gitlab/sidekiq_middleware/concurrency_limit/middleware.rb:32:in `perform', lib/gitlab/sidekiq_middleware/concurrency_limit/server.rb:8:in `call', vendor/gems/sidekiq-7.1.6/lib/sidekiq/middleware/chain.rb:182:in `traverse', vendor/gems/sidekiq-7.1.6/lib/sidekiq/middleware/chain.rb:183:in `block in traverse', lib/click_house/migration_support/sidekiq_middleware.rb:7:in `call', vendor/gems/sidekiq-7.1.6/lib/sidekiq/middleware/chain.rb:182:in `traverse', vendor/gems/sidekiq-7.1.6/lib/sidekiq/middleware/chain.rb:183:in `block in traverse', lib/gitlab/sidekiq_middleware/pause_control/strategies/base.rb:31:in `perform', lib/gitlab/sidekiq_middleware/pause_control/strategy_handler.rb:22:in `perform', lib/gitlab/sidekiq_middleware/pause_control/server.rb:8:in `call', vendor/gems/sidekiq-7.1.6/lib/sidekiq/middleware/chain.rb:182:in `traverse', vendor/gems/sidekiq-7.1.6/lib/sidekiq/middleware/chain.rb:183:in `block in traverse', lib/gitlab/application_context.rb:133:in `block in use', gitlab-labkit (0.36.0) lib/labkit/context.rb:35:in `with_context', lib/gitlab/application_context.rb:133:in `use', lib/gitlab/sidekiq_middleware/worker_context.rb:11:in `wrap_in_optional_context', lib/gitlab/sidekiq_middleware/worker_context/server.rb:19:in `block in call', lib/gitlab/application_context.rb:133:in `block in use', gitlab-labkit (0.36.0) lib/labkit/context.rb:35:in `with_context', lib/gitlab/application_context.rb:133:in `use', lib/gitlab/application_context.rb:66:in `with_context', lib/gitlab/sidekiq_middleware/worker_context/server.rb:17:in `call', vendor/gems/sidekiq-7.1.6/lib/sidekiq/middleware/chain.rb:182:in `traverse', vendor/gems/sidekiq-7.1.6/lib/sidekiq/middleware/chain.rb:183:in `block in traverse', lib/gitlab/sidekiq_status/server_middleware.rb:7:in `call', vendor/gems/sidekiq-7.1.6/lib/sidekiq/middleware/chain.rb:182:in `traverse', vendor/gems/sidekiq-7.1.6/lib/sidekiq/middleware/chain.rb:183:in `block in traverse', lib/gitlab/sidekiq_versioning/middleware.rb:9:in `call', vendor/gems/sidekiq-7.1.6/lib/sidekiq/middleware/chain.rb:182:in `traverse', vendor/gems/sidekiq-7.1.6/lib/sidekiq/middleware/chain.rb:183:in `block in traverse', lib/gitlab/sidekiq_middleware/query_analyzer.rb:7:in `block in call', lib/gitlab/database/query_analyzer.rb:40:in `within', lib/gitlab/sidekiq_middleware/query_analyzer.rb:7:in `call', vendor/gems/sidekiq-7.1.6/lib/sidekiq/middleware/chain.rb:182:in `traverse', vendor/gems/sidekiq-7.1.6/lib/sidekiq/middleware/chain.rb:183:in `block in traverse', lib/gitlab/sidekiq_middleware/admin_mode/server.rb:14:in `call', vendor/gems/sidekiq-7.1.6/lib/sidekiq/middleware/chain.rb:182:in `traverse', vendor/gems/sidekiq-7.1.6/lib/sidekiq/middleware/chain.rb:183:in `block in traverse', lib/gitlab/sidekiq_middleware/instrumentation_logger.rb:9:in `call', vendor/gems/sidekiq-7.1.6/lib/sidekiq/middleware/chain.rb:182:in `traverse', vendor/gems/sidekiq-7.1.6/lib/sidekiq/middleware/chain.rb:183:in `block in traverse', lib/gitlab/sidekiq_middleware/batch_loader.rb:7:in `call', vendor/gems/sidekiq-7.1.6/lib/sidekiq/middleware/chain.rb:182:in `traverse', vendor/gems/sidekiq-7.1.6/lib/sidekiq/middleware/chain.rb:183:in `block in traverse', lib/gitlab/sidekiq_middleware/extra_done_log_metadata.rb:7:in `call', vendor/gems/sidekiq-7.1.6/lib/sidekiq/middleware/chain.rb:182:in `traverse', vendor/gems/sidekiq-7.1.6/lib/sidekiq/middleware/chain.rb:183:in `block in traverse', lib/gitlab/sidekiq_middleware/server_metrics.rb:111:in `block in call', lib/gitlab/sidekiq_middleware/server_metrics.rb:139:in `block in instrument', lib/gitlab/metrics/background_transaction.rb:33:in `run', lib/gitlab/sidekiq_middleware/server_metrics.rb:139:in `instrument', lib/gitlab/sidekiq_middleware/server_metrics.rb:110:in `call', vendor/gems/sidekiq-7.1.6/lib/sidekiq/middleware/chain.rb:182:in `traverse', vendor/gems/sidekiq-7.1.6/lib/sidekiq/middleware/chain.rb:183:in `block in traverse', lib/gitlab/sidekiq_middleware/request_store_middleware.rb:8:in `block in call', gems/gitlab-safe_request_store/lib/gitlab/safe_request_store.rb:66:in `enabling_request_store', gems/gitlab-safe_request_store/lib/gitlab/safe_request_store.rb:59:in `ensure_request_store', lib/gitlab/sidekiq_middleware/request_store_middleware.rb:7:in `call', vendor/gems/sidekiq-7.1.6/lib/sidekiq/middleware/chain.rb:182:in `traverse', vendor/gems/sidekiq-7.1.6/lib/sidekiq/middleware/chain.rb:183:in `block in traverse', gitlab-labkit (0.36.0) lib/labkit/middleware/sidekiq/server.rb:21:in `block in call', vendor/gems/sidekiq-7.1.6/lib/sidekiq/middleware/chain.rb:180:in `traverse', vendor/gems/sidekiq-7.1.6/lib/sidekiq/middleware/chain.rb:183:in `block in traverse', gitlab-labkit (0.36.0) lib/labkit/middleware/sidekiq/context/server.rb:16:in `block in call', gitlab-labkit (0.36.0) lib/labkit/context.rb:35:in `with_context', gitlab-labkit (0.36.0) lib/labkit/middleware/sidekiq/context/server.rb:15:in `call', vendor/gems/sidekiq-7.1.6/lib/sidekiq/middleware/chain.rb:182:in `traverse', vendor/gems/sidekiq-7.1.6/lib/sidekiq/middleware/chain.rb:173:in `invoke', gitlab-labkit (0.36.0) lib/labkit/middleware/sidekiq/server.rb:20:in `call', vendor/gems/sidekiq-7.1.6/lib/sidekiq/middleware/chain.rb:182:in `traverse', vendor/gems/sidekiq-7.1.6/lib/sidekiq/middleware/chain.rb:183:in `block in traverse', lib/gitlab/sidekiq_middleware/monitor.rb:10:in `block in call', lib/gitlab/sidekiq_daemon/monitor.rb:46:in `within_job', lib/gitlab/sidekiq_middleware/monitor.rb:9:in `call', vendor/gems/sidekiq-7.1.6/lib/sidekiq/middleware/chain.rb:182:in `traverse', vendor/gems/sidekiq-7.1.6/lib/sidekiq/middleware/chain.rb:183:in `block in traverse', lib/gitlab/sidekiq_middleware/shard_awareness_validator.rb:10:in `block in call', lib/gitlab/sidekiq_sharding/validator.rb:42:in `enabled', lib/gitlab/sidekiq_middleware/shard_awareness_validator.rb:9:in `call', vendor/gems/sidekiq-7.1.6/lib/sidekiq/middleware/chain.rb:182:in `traverse', vendor/gems/sidekiq-7.1.6/lib/sidekiq/middleware/chain.rb:183:in `block in traverse', lib/gitlab/sidekiq_middleware/size_limiter/server.rb:13:in `call', vendor/gems/sidekiq-7.1.6/lib/sidekiq/middleware/chain.rb:182:in `traverse', vendor/gems/sidekiq-7.1.6/lib/sidekiq/middleware/chain.rb:183:in `block in traverse', marginalia (1.11.1) lib/marginalia/sidekiq_instrumentation.rb:9:in `call', vendor/gems/sidekiq-7.1.6/lib/sidekiq/middleware/chain.rb:182:in `traverse', vendor/gems/sidekiq-7.1.6/lib/sidekiq/middleware/chain.rb:183:in `block in traverse', sentry-sidekiq (5.17.3) lib/sentry/sidekiq/sentry_context_middleware.rb:26:in `call', vendor/gems/sidekiq-7.1.6/lib/sidekiq/middleware/chain.rb:182:in `traverse', vendor/gems/sidekiq-7.1.6/lib/sidekiq/middleware/chain.rb:183:in `block in traverse', vendor/gems/sidekiq-7.1.6/lib/sidekiq/metrics/tracking.rb:26:in `track', vendor/gems/sidekiq-7.1.6/lib/sidekiq/metrics/tracking.rb:122:in `call', vendor/gems/sidekiq-7.1.6/lib/sidekiq/middleware/chain.rb:182:in `traverse', vendor/gems/sidekiq-7.1.6/lib/sidekiq/middleware/chain.rb:173:in `invoke', vendor/gems/sidekiq-7.1.6/lib/sidekiq/processor.rb:179:in `block (3 levels) in process', vendor/gems/sidekiq-7.1.6/lib/sidekiq/processor.rb:140:in `block (6 levels) in dispatch', vendor/gems/sidekiq-7.1.6/lib/sidekiq/job_retry.rb:114:in `local', vendor/gems/sidekiq-7.1.6/lib/sidekiq/processor.rb:139:in `block (5 levels) in dispatch', vendor/gems/sidekiq-7.1.6/lib/sidekiq/rails.rb:16:in `block in call', activesupport (7.0.8.1) lib/active_support/execution_wrapper.rb:92:in `wrap', activesupport (7.0.8.1) lib/active_support/reloader.rb:72:in `block in wrap', activesupport (7.0.8.1) lib/active_support/execution_wrapper.rb:92:in `wrap', activesupport (7.0.8.1) lib/active_support/reloader.rb:71:in `wrap', vendor/gems/sidekiq-7.1.6/lib/sidekiq/rails.rb:15:in `call', vendor/gems/sidekiq-7.1.6/lib/sidekiq/processor.rb:135:in `block (4 levels) in dispatch', vendor/gems/sidekiq-7.1.6/lib/sidekiq/processor.rb:271:in `stats', vendor/gems/sidekiq-7.1.6/lib/sidekiq/processor.rb:130:in `block (3 levels) in dispatch', lib/gitlab/sidekiq_logging/structured_logger.rb:21:in `call', vendor/gems/sidekiq-7.1.6/lib/sidekiq/processor.rb:129:in `block (2 levels) in dispatch', vendor/gems/sidekiq-7.1.6/lib/sidekiq/job_retry.rb:81:in `global', vendor/gems/sidekiq-7.1.6/lib/sidekiq/processor.rb:128:in `block in dispatch', vendor/gems/sidekiq-7.1.6/lib/sidekiq/job_logger.rb:39:in `prepare', vendor/gems/sidekiq-7.1.6/lib/sidekiq/processor.rb:127:in `dispatch', vendor/gems/sidekiq-7.1.6/lib/sidekiq/processor.rb:178:in `block (2 levels) in process', vendor/gems/sidekiq-7.1.6/lib/sidekiq/processor.rb:177:in `handle_interrupt', vendor/gems/sidekiq-7.1.6/lib/sidekiq/processor.rb:177:in `block in process', vendor/gems/sidekiq-7.1.6/lib/sidekiq/processor.rb:176:in `handle_interrupt', vendor/gems/sidekiq-7.1.6/lib/sidekiq/processor.rb:176:in `process', vendor/gems/sidekiq-7.1.6/lib/sidekiq/processor.rb:82:in `process_one', vendor/gems/sidekiq-7.1.6/lib/sidekiq/processor.rb:72:in `run', vendor/gems/sidekiq-7.1.6/lib/sidekiq/component.rb:10:in `watchdog', vendor/gems/sidekiq-7.1.6/lib/sidekiq/component.rb:19:in `block in safe_thread']
exception message
undefined method `first' for nil:NilClass

        group.root_ancestor = root_ancestors_by_id[group.id].first
                                                            ^^^^^^

Possible fixes

The error is being thrown in ElasticIndexBulkCronWorker from Preloaders::GroupRootAncestorPreloader which is called in EpicClassProxy

Edited by 🤖 GitLab Bot 🤖