thoughtbot/factory_bot · error · ArgumentError

Sequence '#{sequence.uri_manager.first}' failed to return a

Error message

Sequence '#{sequence.uri_manager.first}' failed to return a value. Perhaps it needs a scope to operate? (scope: <object>)

What it means

ArgumentError raised by Evaluator#increment_sequence (evaluator.rb:53-62) when a factory sequence attribute fails to evaluate. The sequence block is instance_exec'd against a scope (the evaluator by default), and a bare `rescue` converts ANY exception from sequence.next into this generic ArgumentError — typically a NoMethodError because the block references state the evaluator cannot resolve (the evaluator forwards to the built instance, then SyntaxRunner). It also fires when the returned value stringifies to '#<FactoryBot::Declaration...', i.e. a broken declaration leaked into the value. The original backtrace is discarded, so the real cause is hidden.

Source

Thrown at lib/factory_bot/evaluator.rb:60

      end
    end

    def respond_to_missing?(method_name, _include_private = false)
      @instance.respond_to?(method_name) || SyntaxRunner.new.respond_to?(method_name)
    end

    def __override_names__
      @overrides.keys
    end

    def increment_sequence(sequence, scope: self)
      value = sequence.next(scope)

      raise if value.respond_to?(:start_with?) && value.start_with?("#<FactoryBot::Declaration")

      value
    rescue
      raise ArgumentError, "Sequence '#{sequence.uri_manager.first}' failed to " \
                          "return a value. Perhaps it needs a scope to operate? (scope: <object>)"
    end

    def self.attribute_list
      AttributeList.new.tap do |list|
        attribute_lists.each do |attribute_list|
          list.apply_attributes attribute_list.to_a
        end
      end
    end

    def self.define_attribute(name, &block)
      if instance_methods(false).include?(name) || private_instance_methods(false).include?(name)
        undef_method(name)
      end

      define_method(name) do
        if @cached_attributes.key?(name)

View on GitHub (pinned to 18ae8b581b)

Solutions

  1. Reproduce the real error outside the guard: call `seq = FactoryBot::Sequence.find(:user, :info); seq.next(probe_object)` with an object that mirrors the intended scope — the original exception and backtrace appear.
  2. Fix the underlying nil/NoMethodError inside the sequence block (provide defaults, reorder attribute dependencies).
  3. If the sequence needs instance state, pass an explicit scope that responds to every method the block uses: generate(:user, :info, scope: user).
  4. Keep factory sequences self-contained (`|n| "user#{n}@example.com"`) and derive dependent values in ordinary attribute blocks, which see other attributes through the evaluator.

Example fix

# before
FactoryBot.define do
  factory :user do
    sequence(:info) { |n| "#{name}:#{age + n}" } # name/age unreachable from evaluator
  end
end

# after
FactoryBot.define do
  factory :user do
    name { 'Jester' }
    age { 21 }
    info { "#{name}:#{age}" } # attribute blocks see other attributes via the evaluator
  end
end
Defensive patterns

Strategy: validation

Validate before calling

# smoke-test a scope-dependent sequence before relying on the factory
seq = FactoryBot::Sequence.find(:user, :info)
probe = User.new(name: 'x', age: 1)
begin
  seq.next(probe) # surfaces the real error before the evaluator's rescue wraps it
rescue => e
  raise ArgumentError, "sequence :info is broken: #{e.class}: #{e.message}"
end

Type guard

->(scope, *methods) { !scope.nil? && methods.all? { |m| scope.respond_to?(m) } }

Try / catch

begin
  FactoryBot.build(:user)
rescue ArgumentError => e
  raise unless e.message.include?('failed to return a value')
  # re-run the sequence block manually with the intended scope to recover the hidden exception
end

Prevention

When it happens

Trigger: Define `factory :user do sequence(:info) { |n| "#{name}:#{age + n}" } end` where the built instance does not respond to name/age or they are nil, then build(:user): the block raises NoMethodError/TypeError inside the evaluator, and the rescue rewrites it to "Sequence 'user/info' failed to return a value. Perhaps it needs a scope to operate?". Any typo'd method or nil arithmetic inside a sequence block produces the same message.

Common situations: Sequences that depend on other attributes or model state; nil arithmetic (`age + n` when age is nil); model refactors that rename methods still referenced in sequence blocks; CI failures that look opaque because the rescue swallowed the underlying error.

Related errors


AI-assisted analysis of thoughtbot/factory_bot@18ae8b581b (2026-08-21). Data as JSON: /api/errors/0357fe3fe0ccfc8f. Report an issue: GitHub.