# Buggy code
def tile(cls, op):
    check_chunks_unknown_shape(op.inputs, TilesError)
    tensor = op.outputs[0]

    m = op.input
    k = op.k
    is_triu = type(op) == TensorTriu

    fx = lambda x, y: x - y + k
    nsplits = m.nsplits
    cum_size = [np.cumsum(s) for s in nsplits]

    out_chunks = []
    for out_idx in itertools.product(*[range(len(s)) for s in nsplits]):
        i, j = out_idx[-2:]
        ld_pos = cum_size[-2][i] - 1, cum_size[-1][j] - nsplits[-1][j]
        ru_pos = cum_size[-2][i] - nsplits[-2][i], cum_size[-1][j] - 1

        ld_fx = fx(*ld_pos)
        ru_fx = fx(*ru_pos)

        chunk_shape = tuple(nsplits[i][idx] for i, idx in enumerate(out_idx))
        if (is_triu and ld_fx > 0 and ru_fx > 0) or (
            not is_triu and ld_fx < 0 and ru_fx < 0
        ):
            # does not cross, fill with zeros
            chunk_op = TensorZeros(dtype=op.dtype, gpu=op.gpu, sparse=op.sparse)
            out_chunk = chunk_op.new_chunk(
                None, shape=chunk_shape, index=out_idx, order=tensor.order
            )
        else:
            lu_pos = ru_pos[0], ld_pos[1]
            chunk_k = fx(*lu_pos)

            input_chunk = m.cix[out_idx]
            chunk_op = op.to_chunk_op(chunk_k)
            out_chunk = chunk_op.new_chunk(
                [input_chunk], shape=chunk_shape, index=out_idx, order=tensor.order
            )

        out_chunks.append(out_chunk)

    new_op = op.copy()
    return new_op.new_tensors(
        op.inputs, tensor.shape, chunks=out_chunks, nsplits=m.nsplits
    )


# Traceback (AttributeError)
In [3]: import pandas as pd

In [4]: data = pd.DataFrame(np.arange(20).reshape((4, 5)) + 1, columns=['a', 'b', 'c', 'd', 'e'])

In [6]: df = md.DataFrame(data)

In [7]: df.groupby(['a','b']).size().execute()
Unexpected exception occurred in enter_build_mode.<locals>.inner.
Traceback (most recent call last):
File "/Users/hekaisheng/Documents/mars_dev/mars/mars/utils.py", line 353, in _wrapped
return func(*args, **kwargs)
File "/Users/hekaisheng/Documents/mars_dev/mars/mars/utils.py", line 493, in inner
return func(*args, **kwargs)
File "/Users/hekaisheng/Documents/mars_dev/mars/mars/scheduler/graph.py", line 633, in prepare_graph
self._target_tileable_datas + fetch_tileables, tileable_graph)
File "/Users/hekaisheng/Documents/mars_dev/mars/mars/utils.py", line 399, in _wrapped
return func(*args, **kwargs)
File "/Users/hekaisheng/Documents/mars_dev/mars/mars/utils.py", line 493, in inner
return func(*args, **kwargs)
File "/Users/hekaisheng/Documents/mars_dev/mars/mars/tiles.py", line 350, in build
tileables, tileable_graph=tileable_graph)
File "/Users/hekaisheng/Documents/mars_dev/mars/mars/utils.py", line 399, in _wrapped
return func(*args, **kwargs)
File "/Users/hekaisheng/Documents/mars_dev/mars/mars/utils.py", line 493, in inner
return func(*args, **kwargs)
File "/Users/hekaisheng/Documents/mars_dev/mars/mars/tiles.py", line 263, in build
self._on_tile_failure(tileable_data.op, exc_info)
File "/Users/hekaisheng/Documents/mars_dev/mars/mars/tiles.py", line 302, in inner
raise exc_info[1].with_traceback(exc_info[2]) from None
File "/Users/hekaisheng/Documents/mars_dev/mars/mars/tiles.py", line 243, in build
tiled = self._tile(tileable_data, tileable_graph)
File "/Users/hekaisheng/Documents/mars_dev/mars/mars/tiles.py", line 338, in _tile
return super()._tile(tileable_data, tileable_graph)
File "/Users/hekaisheng/Documents/mars_dev/mars/mars/tiles.py", line 203, in _tile
tds = on_tile(tileable_data.op.outputs, tds)
File "/Users/hekaisheng/Documents/mars_dev/mars/mars/scheduler/graph.py", line 615, in on_tile
return self.context.wraps(handler.dispatch)(first.op)
File "/Users/hekaisheng/Documents/mars_dev/mars/mars/context.py", line 69, in h
return func(*args, **kwargs)
File "/Users/hekaisheng/Documents/mars_dev/mars/mars/utils.py", line 399, in _wrapped
return func(*args, **kwargs)
File "/Users/hekaisheng/Documents/mars_dev/mars/mars/tiles.py", line 119, in dispatch
tiled = op_cls.tile(op)
File "/Users/hekaisheng/Documents/mars_dev/mars/mars/dataframe/groupby/aggregation.py", line 481, in tile
return cls._tile_with_tree(op)
File "/Users/hekaisheng/Documents/mars_dev/mars/mars/dataframe/groupby/aggregation.py", line 412, in _tile_with_tree
index = out_df.index_value.to_pandas()
File "/Users/hekaisheng/Documents/mars_dev/mars/mars/dataframe/core.py", line 283, in to_pandas
return self._index_value.to_pandas()
File "/Users/hekaisheng/Documents/mars_dev/mars/mars/dataframe/core.py", line 197, in to_pandas
sortorder=self._sortorder, names=self._names)
AttributeError: _sortorder

# Fixed code
def tile(cls, op):
    check_chunks_unknown_shape(op.inputs, TilesError)
    tensor = op.outputs[0]

    m = op.input
    k = op.k
    is_triu = type(op) == TensorTriu

    fx = lambda x, y: x - y + k
    nsplits = m.nsplits
    cum_size = [np.cumsum(s).tolist() for s in nsplits]

    out_chunks = []
    for out_idx in itertools.product(*[range(len(s)) for s in nsplits]):
        i, j = out_idx[-2:]
        ld_pos = cum_size[-2][i] - 1, cum_size[-1][j] - nsplits[-1][j]
        ru_pos = cum_size[-2][i] - nsplits[-2][i], cum_size[-1][j] - 1

        ld_fx = fx(*ld_pos)
        ru_fx = fx(*ru_pos)

        chunk_shape = tuple(nsplits[i][idx] for i, idx in enumerate(out_idx))
        if (is_triu and ld_fx > 0 and ru_fx > 0) or (
            not is_triu and ld_fx < 0 and ru_fx < 0
        ):
            # does not cross, fill with zeros
            chunk_op = TensorZeros(dtype=op.dtype, gpu=op.gpu, sparse=op.sparse)
            out_chunk = chunk_op.new_chunk(
                None, shape=chunk_shape, index=out_idx, order=tensor.order
            )
        else:
            lu_pos = ru_pos[0], ld_pos[1]
            chunk_k = fx(*lu_pos)

            input_chunk = m.cix[out_idx]
            chunk_op = op.to_chunk_op(chunk_k)
            out_chunk = chunk_op.new_chunk(
                [input_chunk], shape=chunk_shape, index=out_idx, order=tensor.order
            )

        out_chunks.append(out_chunk)

    new_op = op.copy()
    return new_op.new_tensors(
        op.inputs, tensor.shape, chunks=out_chunks, nsplits=m.nsplits
    )