gitlabhq/gitlabhq · error · ArgumentError

Invalid relation: #{entry.inspect}

Error message

Invalid relation: #{entry.inspect}

What it means

Ci::Preloaders::CommitStatusPreloader's relation filter raises ArgumentError, "Invalid relation: #{entry.inspect}" when an element of the relations argument is neither an object responding to to_sym (Symbol/String) nor a Hash. Each entry must resolve to a reflection name on the klass (commit statuses) or a Hash whose keys are reflection names; anything else — Integer, Array, nil — is rejected as invalid.

Source

Thrown at app/models/ci/preloaders/commit_status_preloader.rb:41

      def objects(klass)
        @statuses.select { |job| job.is_a?(klass) }
      end

      def associations(klass, relations)
        klass_reflections = klass.reflections.keys.map(&:to_sym).to_set

        result = []
        relations.each do |entry|
          if entry.respond_to?(:to_sym)
            result << entry.to_sym if klass_reflections.include?(entry.to_sym)
          elsif entry.is_a?(Hash)
            entry = entry.select do |key, _value|
              klass_reflections.include?(key.to_sym)
            end

            result << entry if entry.present?
          else
            raise ArgumentError, "Invalid relation: #{entry.inspect}"
          end
        end

        result
      end
    end
  end
end

View on GitHub (pinned to 55ee20384a)

Solutions

  1. Pass a flat array of Symbols/Strings and/or Hashes only, e.g. [:project, :runner, { tags: :pipeline }]
  2. Flatten and compact the list before calling: relations.flatten.compact
  3. Filter names against the model's reflections before invoking if the list is user-derived

Example fix

# before
relations = [:project, [:runner, nil]] # inner Array + nil entries -> raises
CommitStatusPreloader.new(statuses).preload(relation_names: relations)

# after
relations = [:project, :runner, { tags: {} }].flatten.compact
CommitStatusPreloader.new(statuses).preload(relation_names: relations)
Defensive patterns

Strategy: type-guard

Validate before calling

relations = relations.flatten.compact
raise ArgumentError, relations.inspect unless relations.all? { |r| r.respond_to?(:to_sym) || r.is_a?(Hash) }
# names must also exist as reflections on the preloaded klass
valid = Ci::Build.reflect_on_all_associations.map { |_, rel| rel.name.to_s }
relations.select! { |r| valid.include?(r.to_s) } unless relations.all?(Hash)

Type guard

def valid_preload_entries?(entries)
  entries.flatten.compact.all? { |e| e.respond_to?(:to_sym) || e.is_a?(Hash) }
end

Try / catch

begin
  Ci::Preloaders::CommitStatusPreloader.new(statuses).preload(relation_names: relations)
rescue ArgumentError => e
  raise unless e.message.start_with?('Invalid relation:')
  # log the inspected entry and fall back to a hardcoded safe relation list
end

Prevention

When it happens

Trigger: Calling the preloader with nested arrays like [:stage, [:tags]] where the inner array element is itself an Array; passing nil inside the list (e.g. from params[relation]&.to_a); passing an AR object or integer id instead of a relation name.

Common situations: Building preload lists dynamically from user-supplied `includes` parameters; merging hardcoded and computed relation lists where one side yields arrays or nils; refactoring symbol lists into nested structures.

Related errors


AI-assisted analysis of gitlabhq/gitlabhq@55ee20384a (2026-08-21). Data as JSON: /api/errors/e504bf709cb6f7f9. Report an issue: GitHub.