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 the private Syntax::Methods#increment_sequence (methods.rb:169-178) that backs the public generate/generate_list API. Here scope defaults to nil, so a sequence block written against instance state (`sequence(:info) { |n| "#{name}:#{age + n}" }`) executes with no scope and fails; the bare rescue rewrites any exception from sequence.next into this generic ArgumentError, naming the sequence's URI from sequence.uri_manager (e.g. 'user/info'). The underlying exception is hidden.
Source
Thrown at lib/factory_bot/syntax/methods.rb:176
private
##
# Increments the given sequence and returns the value.
#
# Arguments:
# sequence:
# The sequence instance
# scope: (object)(optional)
# The object the sequence should be evaluated within
#
def increment_sequence(sequence, scope: nil)
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
end
end
end
View on GitHub (pinned to 18ae8b581b)
Solutions
- Pass an explicit scope that provides every method the block references: `generate(:user, :info, scope: user)`.
- If the sequence should be stateless, rewrite it to use only the counter: `sequence(:info) { |n| "user-#{n}" }`.
- For lists, thread the same scope: `generate_list(:user, :info, 5, scope: user)`.
- While debugging, call the sequence directly (e.g. `FactoryBot::Sequence.find(:user, :info).next(user)`) to see the original exception before factory_bot rewrites it.
Example fix
# before generate(:user, :info) # ArgumentError: state-dependent sequence, no scope # after user = build(:user, name: 'Jester', age: 21) generate(:user, :info, scope: user)
Defensive patterns
Strategy: validation
Validate before calling
# wrapper that refuses scope-less calls to state-dependent sequences def generate_scoped!(*uri, scope:) raise ArgumentError, 'scope: is required for this sequence' if scope.nil? generate(*uri, scope: scope) end
Type guard
->(scope) { !scope.nil? } Try / catch
begin
generate(:user, :info)
rescue ArgumentError => e
raise unless e.message.include?('failed to return a value')
# either pass scope: or rewrite the sequence to be self-contained
end Prevention
- Treat generate without scope: as valid only for stateless sequences.
- Write sequences using only |n| unless a scope is guaranteed at every call site.
- Debug by calling sequence.next(scope) directly — the rescue hides the underlying exception.
When it happens
Trigger: Per spec/acceptance/sequence_spec.rb:203-219: define `factory :user do sequence(:info) { |n| "#{name}:#{age + n}" } end`; then `generate(:user, :info)` raises "Sequence 'user/info' failed to return a value. Perhaps it needs a scope to operate?", while `generate(:user, :info, scope: jester)` with an object that has name/age succeeds. Any other exception inside the block (typo, nil arithmetic) reached via generate/generate_list produces the same error.
Common situations: Calling global generate for a sequence originally written against factory instance state; refactoring an inline factory sequence into a shared/global one; NoMethodError-on-nil hidden by the generic message, making failures hard to diagnose in CI.
Related errors
- Sequence '#{sequence.uri_manager.first}' failed to return a
- Association '#{name}' received an invalid factory argument.
- Association '#{name}' received an invalid attribute override
- undefined method '#{name}' in '#{@definition.name}' factory
- Unexpected block passed to '#{name}' association in '#{@defi
AI-assisted analysis of thoughtbot/factory_bot@18ae8b581b (2026-08-21).
Data as JSON: /api/errors/18dae8062bfa0e20.
Report an issue: GitHub.