# Buggy code
def verylong_encoder(obj):
    if isinstance(obj, dict):
        for key, value in six.iteritems(obj.copy()):
            obj[key] = verylong_encoder(value)
        return dict(obj)
    elif isinstance(obj, (list, tuple)):
        obj = list(obj)
        for idx, entry in enumerate(obj):
            obj[idx] = verylong_encoder(entry)
        return obj
    # A value of an Integer object is limited from -(2^63) upto (2^64)-1 by MessagePack
    # spec. Here we care only of JIDs that are positive integers.
    if isinstance(obj, six.integer_types) and obj >= pow(2, 64):
        return six.text_type(obj)
    else:
        return obj


# Traceback (RuntimeError)
Process Process-1:926:
Traceback (most recent call last):
File "/usr/lib/python2.7/multiprocessing/process.py", line 258, in _bootstrap
self.run()
File "/usr/lib/python2.7/multiprocessing/process.py", line 114, in run
self._target(*self._args, **self._kwargs)
File "/usr/lib/python2.7/dist-packages/salt/utils/schedule.py", line 737, in handle_func
channel.send(load)
File "/usr/lib/python2.7/dist-packages/salt/utils/async.py", line 74, in wrap
ret = self._block_future(ret)
File "/usr/lib/python2.7/dist-packages/salt/utils/async.py", line 84, in _block_future
return future.result()
File "/usr/lib/python2.7/dist-packages/tornado/concurrent.py", line 215, in result
raise_exc_info(self._exc_info)
File "/usr/lib/python2.7/dist-packages/tornado/gen.py", line 876, in run
yielded = self.gen.throw(*exc_info)
File "/usr/lib/python2.7/dist-packages/salt/transport/zeromq.py", line 240, in send
ret = yield self._crypted_transfer(load, tries=tries, timeout=timeout)
File "/usr/lib/python2.7/dist-packages/tornado/gen.py", line 870, in run
value = future.result()
File "/usr/lib/python2.7/dist-packages/tornado/concurrent.py", line 215, in result
raise_exc_info(self._exc_info)
File "/usr/lib/python2.7/dist-packages/tornado/gen.py", line 876, in run
yielded = self.gen.throw(*exc_info)
File "/usr/lib/python2.7/dist-packages/salt/transport/zeromq.py", line 208, in _crypted_transfer
ret = yield _do_transfer()
File "/usr/lib/python2.7/dist-packages/tornado/gen.py", line 870, in run
value = future.result()
File "/usr/lib/python2.7/dist-packages/tornado/concurrent.py", line 215, in result
raise_exc_info(self._exc_info)
File "/usr/lib/python2.7/dist-packages/tornado/gen.py", line 230, in wrapper
yielded = next(result)
File "/usr/lib/python2.7/dist-packages/salt/transport/zeromq.py", line 192, in _do_transfer
self._package_load(self.auth.crypticle.dumps(load)),
File "/usr/lib/python2.7/dist-packages/salt/crypt.py", line 1187, in dumps
return self.encrypt(self.PICKLE_PAD + self.serial.dumps(obj))
File "/usr/lib/python2.7/dist-packages/salt/payload.py", line 164, in dumps
return msgpack.dumps(verylong_encoder(msg))
File "/usr/lib/python2.7/dist-packages/salt/payload.py", line 149, in verylong_encoder
obj[key] = verylong_encoder(value)
File "/usr/lib/python2.7/dist-packages/salt/payload.py", line 154, in verylong_encoder
obj[idx] = verylong_encoder(entry)
File "/usr/lib/python2.7/dist-packages/salt/payload.py", line 149, in verylong_encoder
obj[key] = verylong_encoder(value)
...
(1000 repeated lines)
...
File "/usr/lib/python2.7/dist-packages/salt/payload.py", line 154, in verylong_encoder
obj[idx] = verylong_encoder(entry)
File "/usr/lib/python2.7/dist-packages/salt/payload.py", line 149, in verylong_encoder
obj[key] = verylong_encoder(value)
File "/usr/lib/python2.7/dist-packages/salt/payload.py", line 154, in verylong_encoder
obj[idx] = verylong_encoder(entry)
File "/usr/lib/python2.7/dist-packages/salt/payload.py", line 151, in verylong_encoder
elif isinstance(obj, (list, tuple)):
RuntimeError: maximum recursion depth exceeded while calling a Python object

# Fixed code
def verylong_encoder(obj, context):
    # Make sure we catch recursion here.
    objid = id(obj)
    if objid in context:
        return "<Recursion on {} with id={}>".format(type(obj).__name__, id(obj))
    context.add(objid)

    if isinstance(obj, dict):
        for key, value in six.iteritems(obj.copy()):
            obj[key] = verylong_encoder(value, context)
        return dict(obj)
    elif isinstance(obj, (list, tuple)):
        obj = list(obj)
        for idx, entry in enumerate(obj):
            obj[idx] = verylong_encoder(entry, context)
        return obj
    # A value of an Integer object is limited from -(2^63) upto (2^64)-1 by MessagePack
    # spec. Here we care only of JIDs that are positive integers.
    if isinstance(obj, six.integer_types) and obj >= pow(2, 64):
        return six.text_type(obj)
    else:
        return obj