Skip to content

NoMethodError during GitLab upgrade from 18.1 to 18.2 when pushing to projects

Summary

During GitLab upgrades from version 18.1 to 18.2, the Project#csp_enabled? method throws a NoMethodError when attempting to access organization policy settings before post-deployment migrations have completed. This occurs because MR !196402 (merged) changed the method to rely on data in the organization_policy_setting table, but this table is only populated during post-deployment migrations that run at the end of the Zero-downtime upgrade process.

Steps to Reproduce

  1. Follow Zero-downtime upgrade process to upgrade GitLab from version 18.1 to 18.2. Do not run post-deployment migrations.
  2. Attempt to push code to any projects that existed before the upgrade started. This will trigger Project#csp_enabled? method.
  3. The method will attempt to delegate to organization_policy_setting.csp_enabled? when organization_policy_setting is nil
Post upgrade:
 

gitlabhq_production=# select * from security_policy_settings;
 id | csp_namespace_id | singleton | organization_id
----+------------------+-----------+-----------------
  1 |                  | t         |
(1 row)

Current Behavior

  • NoMethodError is thrown when csp_enabled? is called on a nil organization_policy_setting object
  • Users cannot push code or access project features until post-deployment migrations complete
  • Zero-downtime upgrades are broken due to this error

Expected Behavior

  • The csp_enabled? method should gracefully handle missing organization policy settings
  • GitLab should remain functional during the upgrade process before post-deployment migrations complete

Possible Fixes

Implemented Solution (merged in MR !203295 (merged)): Replace delegation with explicit method that uses safe navigation:

def csp_enabled?(group)
  !!organization_policy_setting&.csp_enabled?(group)
end

Logs and screenshots:

The following exception is generated:

 "exception.backtrace": [
                "ee/app/models/concerns/security/organization_policy_setting.rb:9:in `rescue in csp_enabled?'",
                "ee/app/models/concerns/security/organization_policy_setting.rb:9:in `csp_enabled?'",
                "ee/app/models/ee/project.rb:1542:in `security_orchestration_policy_configuration_parent_group_ids'",
                "ee/app/models/ee/project.rb:1310:in `all_security_orchestration_policy_configurations'",
                "ee/app/services/security/security_orchestration_policies/protected_branches_push_service.rb:24:in `applicable_active_policies'",
                "ee/app/services/security/security_orchestration_policies/protected_branches_push_service.rb:13:in `rules'",
                "ee/app/services/security/security_orchestration_policies/protected_branches_push_service.rb:7:in `execute'",
                "ee/lib/ee/gitlab/checks/security/policy_check.rb:31:in `branch_name_affected_by_policy?'",
                "ee/lib/ee/gitlab/checks/security/policy_check.rb:16:in `block in validate!'",
                "lib/gitlab/checks/timed_logger.rb:27:in `log_timed'",
                "ee/lib/ee/gitlab/checks/security/policy_check.rb:15:in `validate!'",
                "lib/gitlab/checks/single_change_access.rb:58:in `ref_level_checks'",
                "lib/gitlab/checks/single_change_access.rb:32:in `validate!'",
                "lib/gitlab/checks/changes_access.rb:117:in `block in single_access_checks!'",
                "lib/gitlab/checks/changes_access.rb:116:in `each'",
                "lib/gitlab/checks/changes_access.rb:116:in `single_access_checks!'",
                "lib/gitlab/checks/changes_access.rb:27:in `validate!'",
                "lib/gitlab/git_access.rb:391:in `check_access!'",
                "lib/gitlab/git_access.rb:378:in `check_change_access!'",
                "ee/lib/ee/gitlab/git_access.rb:111:in `check_change_access!'",
                "lib/gitlab/git_access.rb:359:in `check_push_access!'",
                "lib/gitlab/git_access.rb:96:in `check'",
                "ee/lib/ee/gitlab/git_access.rb:22:in `check'",
                "lib/api/helpers/internal_helpers.rb:54:in `access_check!'",
                "lib/api/helpers/internal_helpers.rb:35:in `block in access_check_result'",
                "lib/gitlab/auth/current_user_mode.rb:45:in `bypass_session!'",
                "lib/api/helpers/internal_helpers.rb:132:in `with_admin_mode_bypass!'",
                "lib/api/helpers/internal_helpers.rb:34:in `access_check_result'",
                "ee/lib/ee/api/internal/base.rb:90:in `access_check_result'",
                "lib/api/internal/base.rb:88:in `check_allowed'",
                "ee/lib/ee/api/internal/base.rb:22:in `block in check_allowed'",
                "lib/gitlab/ip_address_state.rb:11:in `with'",
                "ee/lib/ee/api/internal/base.rb:21:in `check_allowed'",
                "lib/api/internal/base.rb:182:in `block (2 levels) in <class:Base>'",
                "lib/gitlab/middleware/ip_address.rb:11:in `call'",
                "lib/api/api_guard.rb:266:in `call'",
                "config/initializers/action_dispatch_journey_router.rb:52:in `block in find_routes'",
                "config/initializers/action_dispatch_journey_router.rb:25:in `map!'",
                "config/initializers/action_dispatch_journey_router.rb:25:in `find_routes'",
                "lib/gitlab/metrics/elasticsearch_rack_middleware.rb:16:in `call'",
                "lib/gitlab/middleware/sidekiq_shard_awareness_validation.rb:20:in `block in call'",
                "lib/gitlab/sidekiq_sharding/validator.rb:42:in `enabled'",
                "lib/gitlab/middleware/sidekiq_shard_awareness_validation.rb:20:in `call'",
                "lib/gitlab/middleware/memory_report.rb:13:in `call'",
                "lib/gitlab/middleware/speedscope.rb:13:in `call'",
                "lib/gitlab/database/load_balancing/rack_middleware.rb:23:in `call'",
                "lib/gitlab/middleware/rails_queue_duration.rb:33:in `call'",
                "lib/gitlab/etag_caching/middleware.rb:21:in `call'",
                "lib/gitlab/metrics/rack_middleware.rb:16:in `block in call'",
                "lib/gitlab/metrics/web_transaction.rb:46:in `run'",
                "lib/gitlab/metrics/rack_middleware.rb:16:in `call'",
                "lib/gitlab/middleware/go.rb:21:in `call'",
                "lib/gitlab/middleware/query_analyzer.rb:11:in `block in call'",
                "lib/gitlab/database/query_analyzer.rb:83:in `within'",
                "lib/gitlab/middleware/query_analyzer.rb:11:in `call'",
                "lib/ci/job_token/middleware.rb:11:in `call'",
                "lib/gitlab/middleware/multipart.rb:173:in `call'",
                "lib/gitlab/middleware/read_only/controller.rb:50:in `call'",
                "lib/gitlab/middleware/read_only.rb:18:in `call'",
                "lib/gitlab/middleware/unauthenticated_session_expiry.rb:18:in `call'",
                "lib/gitlab/middleware/secure_headers.rb:11:in `call'",
                "lib/gitlab/middleware/same_site_cookies.rb:27:in `call'",
                "lib/gitlab/middleware/path_traversal_check.rb:40:in `call'",
                "lib/gitlab/middleware/handle_malformed_strings.rb:21:in `call'",
                "lib/gitlab/middleware/basic_health_check.rb:25:in `call'",
                "lib/gitlab/middleware/handle_ip_spoof_attack_error.rb:25:in `call'",
                "lib/gitlab/middleware/request_context.rb:15:in `call'",
                "lib/gitlab/middleware/webhook_recursion_detection.rb:15:in `call'",
                "config/initializers/fix_local_cache_middleware.rb:11:in `call'",
                "lib/gitlab/middleware/compressed_json.rb:44:in `call'",
                "lib/gitlab/middleware/rack_multipart_tempfile_factory.rb:19:in `call'",
                "lib/gitlab/metrics/requests_rack_middleware.rb:83:in `call'",
                "lib/gitlab/middleware/sidekiq_web_static.rb:20:in `call'",
                "lib/gitlab/middleware/release_env.rb:12:in `call'"
            ],
            "exception.cause_class": "NoMethodError",

Affected Versions: GitLab 18.1 → 18.2 upgrades

Customer Impact: Major - Users unable to push code or access projects during upgrade process until post-deployment migrations complete.

Priority: High - Affects zero-downtime upgrades and requires backport to 18.2 version. Fixed in GitLab 18.4, requires backport to 18.2 for affected upgrade path.

References

Edited by Kate Grechishkina