{"record":{"id":"62b335501ade81e8","repo":"thoughtbot/factory_bot","slug":"attribute-already-defined-attribute-name","errorCode":null,"errorMessage":"Attribute already defined: #{attribute.name}","messagePattern":"Attribute already defined: #(.+?)","errorType":"exception","errorClass":"FactoryBot::AttributeDefinitionError","httpStatus":null,"severity":"error","filePath":"lib/factory_bot/attribute_list.rb","lineNumber":51,"sourceCode":"\n    def non_transient\n      AttributeList.new(@name, reject(&:ignored))\n    end\n\n    def apply_attributes(attributes_to_apply)\n      attributes_to_apply.each { |attribute| add_attribute(attribute) }\n    end\n\n    private\n\n    def add_attribute(attribute)\n      @attributes << attribute\n      attribute\n    end\n\n    def ensure_attribute_not_defined!(attribute)\n      if attribute_defined?(attribute.name)\n        raise AttributeDefinitionError, \"Attribute already defined: #{attribute.name}\"\n      end\n    end\n\n    def ensure_attribute_not_self_referencing!(attribute)\n      if attribute.respond_to?(:factory) && attribute.factory == @name\n        message = \"Self-referencing association '#{attribute.name}' in '#{attribute.factory}'\"\n        raise AssociationDefinitionError, message\n      end\n    end\n\n    def attribute_defined?(attribute_name)\n      @attributes.any? do |attribute|\n        attribute.name == attribute_name\n      end\n    end\n  end\nend\n","sourceCodeStart":33,"sourceCodeEnd":69,"githubUrl":"https://github.com/thoughtbot/factory_bot/blob/18ae8b581bf55de681c8adb5f74d32787fd2157f/lib/factory_bot/attribute_list.rb#L33-L69","documentation":"AttributeDefinitionError raised by AttributeList#ensure_attribute_not_defined! (attribute_list.rb:49-53) when two declarations in the same factory body, trait body, or transient block compile to attributes with the same name. Declarations are checked when the attribute list is compiled (first build/create), so the error surfaces lazily. Overriding an attribute inherited from a parent factory is legal — inherited attributes merge via apply_attributes, which bypasses this check.","triggerScenarios":"`factory :user do name { 'A' }; name { 'B' } end`; combining `sequence :email { |n| ... }` with an explicit `email { 'a@b.c' }` in the same body; declaring `email` in both the body and the same transient block (transient shares the definition's declaration list). Raises 'Attribute already defined: name' on first use of the factory.","commonSituations":"Copy-paste of attribute blocks that leaves two similar lines; renaming an attribute without removing the old declaration; adding a sequence for an attribute still set by a block; merging two factories into one body during refactoring.","solutions":["Locate both declarations for the named attribute in that factory/trait/transient body and delete or rename one.","If one is a sequence and one a block, keep the sequence and remove the explicit attribute (or vice versa).","Remember same-body duplicates are the problem — redefining an inherited attribute in a child factory is allowed and not the cause.","Run FactoryBot.lint(traits: true) so duplicates surface in CI with the factory name."],"exampleFix":"# before\nFactoryBot.define do\n  factory :user do\n    email { 'a@example.com' }\n    sequence :email { |n| \"user#{n}@example.com\" } # duplicate :email\n  end\nend\n\n# after\nFactoryBot.define do\n  factory :user do\n    sequence :email { |n| \"user#{n}@example.com\" }\n  end\nend","handlingStrategy":"validation","validationCode":"# after defining, verify no duplicate attribute names before first use\nnames = FactoryBot::Internal.factory_by_name(:user).definition.declarations.map(&:name)\ndups = names.tally.select { |_, c| c > 1 }.keys\nraise \"duplicate attributes in :user factory: #{dups}\" unless dups.empty?","typeGuard":"->(names) { names.size == names.uniq.size }","tryCatchPattern":"begin\n  FactoryBot.build(:user)\nrescue FactoryBot::AttributeDefinitionError => e\n  # e.message names the duplicated attribute; remove or rename one of its declarations\nend","preventionTips":["Search the factory file for an attribute name before adding a new declaration for it.","Never mix `sequence :email` and `email { ... }` in the same factory body.","Remember parent-factory overrides are allowed; only same-body duplicates raise."],"tags":["ruby","factory-bot","attributes","duplicate-definition"],"backgroundTag":"duplicate-definition","analyzedSha":"18ae8b581bf55de681c8adb5f74d32787fd2157f","analyzedAt":"2026-08-21T18:25:33.545Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}