{"record":{"id":"d6f357ef5852ec3e","repo":"instructure/canvas-lms","slug":"partition-resolution-failure-expected-partitioning-field","errorCode":null,"errorMessage":"Partition resolution failure!!!\nExpected \"#{partitioning_field}\" attribute to be present in set and\nhave a value, but was or did not:\n\n#{attributes}\n","messagePattern":"Partition resolution failure!!!\nExpected \"#(.+?)\" attribute to be present in set and\nhave a value, but was or did not:\n\n#(.+?)\n","errorType":"exception","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"gems/canvas_partman/lib/canvas_partman/concerns/partitioned.rb","lineNumber":170,"sourceCode":"        @arel_tables[partition_table_name] ||= Arel::Table.new(partition_table_name, klass: self)\n      end\n\n      # @internal\n      #\n      # Come up with the table name for the partition the record with the given\n      # attribute pairs should be placed in.\n      #\n      # @param [Array<Array<String, Mixed>>] attributes\n      #  Attribute pairs the model is being created/updated with. You can use\n      #  these to infer the partition name, e.g, based on :created_at.\n      #\n      # @return [String]\n      #  The table name for the partition.\n      def infer_partition_table_name(attributes)\n        attr = attributes.detect { |(k, _v)| (k.is_a?(String) ? k : k.name) == partitioning_field }\n\n        if attr.nil? || attr[1].nil?\n          raise ArgumentError, <<~TEXT\n            Partition resolution failure!!!\n            Expected \"#{partitioning_field}\" attribute to be present in set and\n            have a value, but was or did not:\n\n            #{attributes}\n          TEXT\n        end\n\n        if partitioning_strategy == :by_date\n          date = attr[1].is_a?(ActiveModel::Attribute) ? attr[1].value : attr[1]\n          date = date.utc if ActiveRecord.default_timezone == :utc\n\n          case partitioning_interval\n          when :weeks\n            date = date.to_date\n            [table_name, date.cwyear, (\"%02d\" % date.cweek)].join(\"_\")\n          when :months\n            [table_name, date.year, date.month].join(\"_\")","sourceCodeStart":152,"sourceCodeEnd":188,"githubUrl":"https://github.com/instructure/canvas-lms/blob/1c9f0bb8013ed69c4f2efe11fd483025469b7e6c/gems/canvas_partman/lib/canvas_partman/concerns/partitioned.rb#L152-L188","documentation":"CanvasPartman partitions tables by a partitioning_field (e.g. 'created_at' or an id column). infer_partition_table_name scans the attributes hash for that key to compute which partition table to target. If the key is absent or its value is nil, no partition can be determined, so ArgumentError is raised with the offending attributes dumped.","triggerScenarios":"Calling attrs_in_partition_groups or arel_table_from_key_values (e.g. via CanvasPartman#create/dynamic queries) with an attributes hash that omits the partitioning field or sets it to nil.","commonSituations":"Bulk inserts where only some attribute hashes include the partition key; mass-assigning records without timestamps; renaming the partitioning column without updating callers.","solutions":["Ensure every attribute hash passed to partitioned-model creation includes the partitioning field with a non-nil value","Set a default for the partitioning column in your model/callbacks before persisting","Check which caller passed an incomplete attributes set (message prints the full hash)","Rescue ArgumentError around CanvasPartman calls if partial batches are expected"],"exampleFix":"// before\npartman.create(QueuedMessage, body: 'hi')\n// after\npartman.create(QueuedMessage, created_at: Time.now.utc, body: 'hi')","handlingStrategy":"validation","validationCode":"attrs.each { |a| raise ArgumentError, \"missing #{field}\" unless a[field].present? }","typeGuard":"def partition_ready?(attrs, field) = attrs.key?(field.to_s) && !attrs[field.to_s].nil?","tryCatchPattern":null,"preventionTips":["Always include the partitioning field (e.g. created_at) in attribute hashes","Add model callbacks/defaults that populate the partition key","Test bulk-insert paths against partitioned models"],"tags":["ruby","activerecord","partitioning"],"backgroundTag":"missing-required-argument","analyzedSha":"1c9f0bb8013ed69c4f2efe11fd483025469b7e6c","analyzedAt":"2026-09-15T20:33:18.891Z","contentChangedAt":"2026-09-15T20:33:18.891Z","schemaVersion":2},"datasetVersion":"2026-09-23T02:17:17.105Z"}