gitlabhq/gitlabhq · error · ArgumentError
pipeline not fully loaded
Error message
pipeline not fully loaded
What it means
Ci::Pipeline#age_in_minutes raises ArgumentError, 'pipeline not fully loaded' when the in-memory pipeline object lacks the created_at attribute (has_attribute?(:created_at) is false). This happens when the record was instantiated from a column projection that did not include created_at — the method cannot compute an age from a missing timestamp. Unpersisted records return 0 earlier, so only partially selected persisted rows reach the raise.
Source
Thrown at app/models/ci/pipeline.rb:1855
self.builds.latest.build_matchers(project)
end
def cluster_agent_authorizations
strong_memoize(:cluster_agent_authorizations) do
::Clusters::Agents::Authorizations::CiAccess::Finder.new(project).execute
end
end
def has_test_reports?
strong_memoize(:has_test_reports) do
latest_report_builds_in_self_and_project_descendants(::Ci::JobArtifact.of_report_type(:test)).exists?
end
end
def age_in_minutes
return 0 unless persisted?
raise ArgumentError, 'pipeline not fully loaded' unless has_attribute?(:created_at)
return 0 unless created_at
(Time.current - created_at).ceil / 60
end
def merge_request_diff
return unless merge_request?
merge_request.merge_request_diff_for(merge_request_diff_sha, order_by: :id_desc)
end
def auto_cancel_on_job_failure
pipeline_metadata&.auto_cancel_on_job_failure || 'none'
end
def auto_cancel_on_new_commit
pipeline_metadata&.auto_cancel_on_new_commit || 'conservative'View on GitHub (pinned to 55ee20384a)
Solutions
- Include created_at in the query projection: .select(:id, :status, :created_at)
- Or reload the record before computing: pipeline.reload.age_in_minutes
- Return early in caller code when !pipeline.has_attribute?(:created_at) instead of relying on the raise
Example fix
# before
pipelines = project.ci_pipelines.select(:id, :status).limit(10)
pipelines.each { |p| puts p.age_in_minutes } # raises 'pipeline not fully loaded'
# after
pipelines = project.ci_pipelines.select(:id, :status, :created_at).limit(10)
pipelines.each { |p| puts p.age_in_minutes } Defensive patterns
Strategy: type-guard
Validate before calling
# Ensure the instantiated row carries the column before computing age pipeline.reload unless pipeline.has_attribute?(:created_at) pipeline.age_in_minutes
Type guard
def pipeline_age_computable?(pipeline) pipeline.has_attribute?(:created_at) end
Try / catch
begin age = pipeline.age_in_minutes rescue ArgumentError => e raise unless e.message == 'pipeline not fully loaded' age = pipeline.reload.age_in_minutes end
Prevention
- Include created_at in any .select/.pluck-based projection reused for age or duration math
- Wrap convenience getters on projections behind checks like has_attribute?(:created_at)
- In specs, build pipeline doubles with the full attribute set you intend to query
When it happens
Trigger: Calling age_in_minutes on a pipeline from a scoped select, e.g. project.ci_pipelines.select(:id, :status).first.age_in_minutes; instantiating Ci::Pipeline.new(id: some_id) without created_at where persisted? checks pass via assigns (or from a pluck-built struct); loading through a custom from/subquery projection that omits created_at.
Common situations: Performance-tuned queries that select only id/status for large pipeline lists, then calling a convenience method that needs created_at; reporting code reusing minimal projections; specs building pipeline doubles with partial attributes.
Related errors
- Invalid relation: #{entry.inspect}
- UnpersistedJobError
- only a single id is supported
- TooManyTagsError
- Unknown status `#{new_status}`
AI-assisted analysis of gitlabhq/gitlabhq@55ee20384a (2026-08-21).
Data as JSON: /api/errors/8b8665f01c5e0a3f.
Report an issue: GitHub.