# Buggy code
def decide_series_chunk_size(shape, chunk_size, memory_usage):
    from ..config import options

    chunk_size = dictify_chunk_size(shape, chunk_size)
    average_memory_usage = memory_usage / shape[0]

    if len(chunk_size) == len(shape):
        return normalize_chunk_sizes(shape, chunk_size[0])

    max_chunk_size = options.chunk_store_limit
    series_chunk_size = max_chunk_size / average_memory_usage
    return normalize_chunk_sizes(shape, int(series_chunk_size))


# Traceback (TilesError)
In [1]: import pandas as pd

In [2]: a = pd.DataFrame(columns=list('ab'))

In [3]: import mars.dataframe as md

In [4]: md.DataFrame(a).iloc[:2].execute()
---------------------------------------------------------------------------
StopIteration                             Traceback (most recent call last)
<ipython-input-4-426db4e594a4> in <module>
----> 1 md.DataFrame(a).iloc[:2].execute()

~/Documents/mars_dev/mars/mars/core.py in execute(self, session, **kw)
576
577     def execute(self, session=None, **kw):
--> 578         self._data.execute(session, **kw)
579         return self
580

~/Documents/mars_dev/mars/mars/core.py in execute(self, session, **kw)
364
365         # no more fetch, thus just fire run
--> 366         session.run(self, **kw)
367         # return Tileable or ExecutableTuple itself
368         return self

~/Documents/mars_dev/mars/mars/session.py in run(self, *tileables, **kw)
478         tileables = tuple(mt.tensor(t) if not isinstance(t, (Entity, Base)) else t
479                           for t in tileables)
--> 480         result = self._sess.run(*tileables, **kw)
481
482         for t in tileables:

~/Documents/mars_dev/mars/mars/session.py in run(self, *tileables, **kw)
105             # set number of running cores
106             self.context.set_ncores(kw['n_parallel'])
--> 107             res = self._executor.execute_tileables(tileables, **kw)
108             return res
109

~/Documents/mars_dev/mars/mars/utils.py in _wrapped(*args, **kwargs)
406                 _kernel_mode.eager = False
407             _kernel_mode.eager_count = enter_eager_count + 1
--> 408             return func(*args, **kwargs)
409         finally:
410             _kernel_mode.eager_count -= 1

~/Documents/mars_dev/mars/mars/utils.py in inner(*args, **kwargs)
500     def inner(*args, **kwargs):
501         with build_mode():
--> 502             return func(*args, **kwargs)
503     return inner
504

~/Documents/mars_dev/mars/mars/executor.py in execute_tileables(self, tileables, fetch, n_parallel, n_thread, print_progress, mock, compose, name)
862                 # build chunk graph, tile will be done during building
863                 chunk_graph = chunk_graph_builder.build(
--> 864                     tileables, tileable_graph=tileable_graph)
865                 tileable_graph = chunk_graph_builder.prev_tileable_graph
866                 temp_result_keys = set(result_keys)

~/Documents/mars_dev/mars/mars/utils.py in _wrapped(*args, **kwargs)
406                 _kernel_mode.eager = False
407             _kernel_mode.eager_count = enter_eager_count + 1
--> 408             return func(*args, **kwargs)
409         finally:
410             _kernel_mode.eager_count -= 1

~/Documents/mars_dev/mars/mars/utils.py in inner(*args, **kwargs)
500     def inner(*args, **kwargs):
501         with build_mode():
--> 502             return func(*args, **kwargs)
503     return inner
504

~/Documents/mars_dev/mars/mars/tiles.py in build(self, tileables, tileable_graph)
348
349         chunk_graph = super().build(
--> 350             tileables, tileable_graph=tileable_graph)
351         self._iterative_chunk_graphs.append(chunk_graph)
352         if len(self._interrupted_ops) == 0:

~/Documents/mars_dev/mars/mars/utils.py in _wrapped(*args, **kwargs)
406                 _kernel_mode.eager = False
407             _kernel_mode.eager_count = enter_eager_count + 1
--> 408             return func(*args, **kwargs)
409         finally:
410             _kernel_mode.eager_count -= 1

~/Documents/mars_dev/mars/mars/utils.py in inner(*args, **kwargs)
500     def inner(*args, **kwargs):
501         with build_mode():
--> 502             return func(*args, **kwargs)
503     return inner
504

~/Documents/mars_dev/mars/mars/tiles.py in build(self, tileables, tileable_graph)
261                     # for further execution
262                     partial_tiled_chunks = \
--> 263                         self._on_tile_failure(tileable_data.op, exc_info)
264                     if partial_tiled_chunks is not None and \
265                             len(partial_tiled_chunks) > 0:

~/Documents/mars_dev/mars/mars/tiles.py in inner(op, exc_info)
300                     on_tile_failure(op, exc_info)
301                 else:
--> 302                     raise exc_info[1].with_traceback(exc_info[2]) from None
303         return inner
304

~/Documents/mars_dev/mars/mars/tiles.py in build(self, tileables, tileable_graph)
241                 continue
242             try:
--> 243                 tiled = self._tile(tileable_data, tileable_graph)
244                 tiled_op.add(tileable_data.op)
245                 for t, td in zip(tileable_data.op.outputs, tiled):

~/Documents/mars_dev/mars/mars/tiles.py in _tile(self, tileable_data, tileable_graph)
336         if any(inp.op in self._interrupted_ops for inp in tileable_data.inputs):
337             raise TilesError('Tile fail due to failure of inputs')
--> 338         return super()._tile(tileable_data, tileable_graph)
339
340     @kernel_mode

~/Documents/mars_dev/mars/mars/tiles.py in _tile(self, tileable_data, tileable_graph)
199                 t._nsplits = o.nsplits
200         elif on_tile is None:
--> 201             tds[0]._inplace_tile()
202         else:
203             tds = on_tile(tileable_data.op.outputs, tds)

~/Documents/mars_dev/mars/mars/core.py in _inplace_tile(self)
161
162     def _inplace_tile(self):
--> 163         return handler.inplace_tile(self)
164
165     def __getattr__(self, attr):

~/Documents/mars_dev/mars/mars/tiles.py in inplace_tile(self, to_tile)
134         if not to_tile.is_coarse():
135             return to_tile
--> 136         dispatched = self.dispatch(to_tile.op)
137         self._assign_to([d.data for d in dispatched], to_tile.op.outputs)
138         return to_tile

~/Documents/mars_dev/mars/mars/utils.py in _wrapped(*args, **kwargs)
406                 _kernel_mode.eager = False
407             _kernel_mode.eager_count = enter_eager_count + 1
--> 408             return func(*args, **kwargs)
409         finally:
410             _kernel_mode.eager_count -= 1

~/Documents/mars_dev/mars/mars/tiles.py in dispatch(self, op)
117         else:
118             try:
--> 119                 tiled = op_cls.tile(op)
120             except NotImplementedError as ex:
121                 cause = ex

~/Documents/mars_dev/mars/mars/dataframe/indexing/iloc.py in tile(cls, op)
339
340         handler = DataFrameIlocIndexesHandler()
--> 341         return [handler.handle(op)]
342
343     @classmethod

~/Documents/mars_dev/mars/mars/tensor/indexing/index_lib.py in handle(self, op, return_context)
896
897         self._preprocess(context, index_infos)
--> 898         self._process(context, index_infos)
899         self._postprocess(context, index_infos)
900

~/Documents/mars_dev/mars/mars/tensor/indexing/index_lib.py in _process(cls, context, index_infos)
923         index_to_shape = OrderedDict(sorted([(c.index, c.shape) for c in out_chunks],
924                                             key=itemgetter(0)))
--> 925         context.out_nsplits = calc_nsplits(index_to_shape)
926
927     @classmethod

~/Documents/mars_dev/mars/mars/utils.py in calc_nsplits(chunk_idx_to_shape)
664     :return: nsplits
665     """
--> 666     ndim = len(next(iter(chunk_idx_to_shape)))
667     tileable_nsplits = []
668     # for each dimension, record chunk shape whose index is zero on other dimensions

StopIteration:

# Fixed code
def decide_series_chunk_size(shape, chunk_size, memory_usage):
    from ..config import options

    chunk_size = dictify_chunk_size(shape, chunk_size)
    average_memory_usage = memory_usage / shape[0] if shape[0] != 0 else memory_usage

    if len(chunk_size) == len(shape):
        return normalize_chunk_sizes(shape, chunk_size[0])

    max_chunk_size = options.chunk_store_limit
    series_chunk_size = max_chunk_size / average_memory_usage
    return normalize_chunk_sizes(shape, int(series_chunk_size))