To return different values on subsequent calls, e.g. on the first call return first and on the second second:

allow_any_instance_of(Cat).to receive(:play).and_return('first', 'second')

To raise an error on the first call and then recover and call the original on subsequent calls, the above syntax cannot be used. Instead, use and_wrap_original with a block. Within the block you remove a return value from an array and if that is empty, you continue calling the original.

return_values = [proc { raise StandardError }]
 
allow_any_instance_of(Cat).to receive(:play).and_wrap_original do |original, *args|
  return_values.empty? ? original.call(*args) : return_values.shift.call
end