{"record":{"id":"0357fe3fe0ccfc8f","repo":"thoughtbot/factory_bot","slug":"sequence-sequence-uri-manager-first-failed-to","errorCode":null,"errorMessage":"Sequence '#{sequence.uri_manager.first}' failed to return a value. Perhaps it needs a scope to operate? (scope: <object>)","messagePattern":"Sequence '#(.+?)' failed to return a value\\. Perhaps it needs a scope to operate\\? \\(scope: <object>\\)","errorType":"exception","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"lib/factory_bot/evaluator.rb","lineNumber":60,"sourceCode":"      end\n    end\n\n    def respond_to_missing?(method_name, _include_private = false)\n      @instance.respond_to?(method_name) || SyntaxRunner.new.respond_to?(method_name)\n    end\n\n    def __override_names__\n      @overrides.keys\n    end\n\n    def increment_sequence(sequence, scope: self)\n      value = sequence.next(scope)\n\n      raise if value.respond_to?(:start_with?) && value.start_with?(\"#<FactoryBot::Declaration\")\n\n      value\n    rescue\n      raise ArgumentError, \"Sequence '#{sequence.uri_manager.first}' failed to \" \\\n                          \"return a value. Perhaps it needs a scope to operate? (scope: <object>)\"\n    end\n\n    def self.attribute_list\n      AttributeList.new.tap do |list|\n        attribute_lists.each do |attribute_list|\n          list.apply_attributes attribute_list.to_a\n        end\n      end\n    end\n\n    def self.define_attribute(name, &block)\n      if instance_methods(false).include?(name) || private_instance_methods(false).include?(name)\n        undef_method(name)\n      end\n\n      define_method(name) do\n        if @cached_attributes.key?(name)","sourceCodeStart":42,"sourceCodeEnd":78,"githubUrl":"https://github.com/thoughtbot/factory_bot/blob/18ae8b581bf55de681c8adb5f74d32787fd2157f/lib/factory_bot/evaluator.rb#L42-L78","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["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.","Fix the underlying nil/NoMethodError inside the sequence block (provide defaults, reorder attribute dependencies).","If the sequence needs instance state, pass an explicit scope that responds to every method the block uses: generate(:user, :info, scope: user).","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."],"exampleFix":"# before\nFactoryBot.define do\n  factory :user do\n    sequence(:info) { |n| \"#{name}:#{age + n}\" } # name/age unreachable from evaluator\n  end\nend\n\n# after\nFactoryBot.define do\n  factory :user do\n    name { 'Jester' }\n    age { 21 }\n    info { \"#{name}:#{age}\" } # attribute blocks see other attributes via the evaluator\n  end\nend","handlingStrategy":"validation","validationCode":"# smoke-test a scope-dependent sequence before relying on the factory\nseq = FactoryBot::Sequence.find(:user, :info)\nprobe = User.new(name: 'x', age: 1)\nbegin\n  seq.next(probe) # surfaces the real error before the evaluator's rescue wraps it\nrescue => e\n  raise ArgumentError, \"sequence :info is broken: #{e.class}: #{e.message}\"\nend","typeGuard":"->(scope, *methods) { !scope.nil? && methods.all? { |m| scope.respond_to?(m) } }","tryCatchPattern":"begin\n  FactoryBot.build(:user)\nrescue ArgumentError => e\n  raise unless e.message.include?('failed to return a value')\n  # re-run the sequence block manually with the intended scope to recover the hidden exception\nend","preventionTips":["Keep sequence blocks self-contained — use only the counter argument.","Derive state-dependent values in attribute blocks, which can see other attributes through the evaluator.","When a sequence must touch instance state, always pass scope: explicitly and ensure the scope responds to every method used.","Debug hidden causes by calling seq.next(scope) directly — the bare rescue discards the original backtrace."],"tags":["ruby","factory-bot","sequence","scope","wrapped-exception"],"backgroundTag":"sequence-scope-missing","analyzedSha":"18ae8b581bf55de681c8adb5f74d32787fd2157f","analyzedAt":"2026-08-21T18:25:33.545Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}