{"record":{"id":"8b8665f01c5e0a3f","repo":"gitlabhq/gitlabhq","slug":"pipeline-not-fully-loaded","errorCode":null,"errorMessage":"pipeline not fully loaded","messagePattern":"pipeline not fully loaded","errorType":"exception","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"app/models/ci/pipeline.rb","lineNumber":1855,"sourceCode":"      self.builds.latest.build_matchers(project)\n    end\n\n    def cluster_agent_authorizations\n      strong_memoize(:cluster_agent_authorizations) do\n        ::Clusters::Agents::Authorizations::CiAccess::Finder.new(project).execute\n      end\n    end\n\n    def has_test_reports?\n      strong_memoize(:has_test_reports) do\n        latest_report_builds_in_self_and_project_descendants(::Ci::JobArtifact.of_report_type(:test)).exists?\n      end\n    end\n\n    def age_in_minutes\n      return 0 unless persisted?\n\n      raise ArgumentError, 'pipeline not fully loaded' unless has_attribute?(:created_at)\n\n      return 0 unless created_at\n\n      (Time.current - created_at).ceil / 60\n    end\n\n    def merge_request_diff\n      return unless merge_request?\n\n      merge_request.merge_request_diff_for(merge_request_diff_sha, order_by: :id_desc)\n    end\n\n    def auto_cancel_on_job_failure\n      pipeline_metadata&.auto_cancel_on_job_failure || 'none'\n    end\n\n    def auto_cancel_on_new_commit\n      pipeline_metadata&.auto_cancel_on_new_commit || 'conservative'","sourceCodeStart":1837,"sourceCodeEnd":1873,"githubUrl":"https://github.com/gitlabhq/gitlabhq/blob/55ee20384a1f55cb0e362dee1d07149613b1b9bf/app/models/ci/pipeline.rb#L1837-L1873","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"# before\npipelines = project.ci_pipelines.select(:id, :status).limit(10)\npipelines.each { |p| puts p.age_in_minutes } # raises 'pipeline not fully loaded'\n\n# after\npipelines = project.ci_pipelines.select(:id, :status, :created_at).limit(10)\npipelines.each { |p| puts p.age_in_minutes }","handlingStrategy":"type-guard","validationCode":"# Ensure the instantiated row carries the column before computing age\npipeline.reload unless pipeline.has_attribute?(:created_at)\npipeline.age_in_minutes","typeGuard":"def pipeline_age_computable?(pipeline)\n  pipeline.has_attribute?(:created_at)\nend","tryCatchPattern":"begin\n  age = pipeline.age_in_minutes\nrescue ArgumentError => e\n  raise unless e.message == 'pipeline not fully loaded'\n  age = pipeline.reload.age_in_minutes\nend","preventionTips":["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"],"tags":["gitlab","ci","activerecord","partial-load","select"],"backgroundTag":"partially-loaded-record","analyzedSha":"55ee20384a1f55cb0e362dee1d07149613b1b9bf","analyzedAt":"2026-08-21T14:22:27.782Z","schemaVersion":2},"datasetVersion":"2026-08-21T18:17:14.833Z"}