{"record":{"id":"010e06fcaea71367","repo":"thoughtbot/factory_bot","slug":"association-name-received-an-invalid-factory","errorCode":null,"errorMessage":"Association '#{name}' received an invalid factory argument.\nDid you mean? 'factory: :#{factory_name.name}'","messagePattern":"Association '#(.+?)' received an invalid factory argument\\.\nDid you mean\\? 'factory: :#(.+?)'","errorType":"exception","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"lib/factory_bot/declaration/association.rb","lineNumber":41,"sourceCode":"      private\n\n      attr_reader :factory_name, :overrides, :traits\n\n      def build\n        raise_if_arguments_are_declarations!\n\n        [\n          Attribute::Association.new(\n            name,\n            factory_name,\n            [traits, overrides].flatten\n          )\n        ]\n      end\n\n      def raise_if_arguments_are_declarations!\n        if factory_name.is_a?(Declaration)\n          raise ArgumentError.new(<<~MSG)\n            Association '#{name}' received an invalid factory argument.\n            Did you mean? 'factory: :#{factory_name.name}'\n          MSG\n        end\n\n        overrides.each do |attribute, value|\n          if value.is_a?(Declaration)\n            raise ArgumentError.new(<<~MSG)\n              Association '#{name}' received an invalid attribute override.\n              Did you mean? '#{attribute}: :#{value.name}'\n            MSG\n          end\n        end\n      end\n    end\n  end\nend\n","sourceCodeStart":23,"sourceCodeEnd":59,"githubUrl":"https://github.com/thoughtbot/factory_bot/blob/18ae8b581bf55de681c8adb5f74d32787fd2157f/lib/factory_bot/declaration/association.rb#L23-L59","documentation":"Raised by factory_bot when an association's factory option is not a factory name but an implicit Declaration object. Writing `author factory: user` (bare user, no colon) makes DefinitionProxy#method_missing treat `user` as an implicit attribute reference, and that Declaration::Implicit is stored as the factory argument of the association declaration. The guard raise_if_arguments_are_declarations! (association.rb:39-45) detects it when declarations are built, so the error surfaces on the first build/create/lint of the factory, not at definition time.","triggerScenarios":"Define `FactoryBot.define { factory :post do author factory: user end }` (missing the colon before user), then call FactoryBot.build(:post). The bare method call inside the options hash produces a Declaration that becomes factory_name; Association#build raises ArgumentError \"Association 'author' received an invalid factory argument. Did you mean? 'factory: :user'\".","commonSituations":"Hand-typing association options and dropping the colon; copy-paste from docs or older examples where the leading colon is easy to lose; refactors that turn symbol values into bare references. Often first seen in CI because definition files only fail once a factory is actually built or linted.","solutions":["Symbolize the factory target: `association :author, factory: :user` (or the short `author factory: :user`).","If the attribute name already matches the target factory, drop options entirely: `author` implicitly uses the :author factory.","Audit the rest of the options hash — the same typo pattern also triggers the sibling 'invalid attribute override' error.","Add FactoryBot.lint(traits: true) to CI so declaration errors surface deterministically instead of at first use."],"exampleFix":"# before\nFactoryBot.define do\n  factory :post do\n    author factory: user   # bare user becomes a Declaration, not :user\n  end\nend\n\n# after\nFactoryBot.define do\n  factory :post do\n    author factory: :user\n  end\nend","handlingStrategy":"validation","validationCode":"# before defining, verify association factory targets are symbols/strings\noptions = { factory: :user }\nbad = options.reject { |_, v| v.is_a?(Symbol) || v.is_a?(String) }\nraise ArgumentError, \"non-symbol association option values: #{bad.keys}\" unless bad.empty?","typeGuard":"->(v) { v.is_a?(Symbol) || v.is_a?(String) }","tryCatchPattern":"begin\n  FactoryBot.build(:post)\nrescue ArgumentError => e\n  raise unless e.message.include?('invalid factory argument')\n  # a factory option lost its ':' — symbolize it in the association declaration\nend","preventionTips":["Always write association factory targets as symbols: `factory: :user`, never `factory: user`.","Run FactoryBot.lint(traits: true) in CI so declaration errors surface before runtime.","Copy association declarations from a known-good factory instead of typing option hashes by hand."],"tags":["ruby","factory-bot","association","argumenterror","typo"],"backgroundTag":"wrong-argument-type","analyzedSha":"18ae8b581bf55de681c8adb5f74d32787fd2157f","analyzedAt":"2026-08-21T18:25:33.545Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}