# Buggy code
def _tile_offset(cls, op: "DataFrameReadSQL"):
    df = op.outputs[0]

    if op.row_memory_usage is not None:
        # Data selected
        chunk_size = df.extra_params.raw_chunk_size or options.chunk_size
        if chunk_size is None:
            chunk_size = (
                int(options.chunk_store_limit / op.row_memory_usage),
                df.shape[1],
            )
        row_chunk_sizes = normalize_chunk_sizes(df.shape, chunk_size)[0]
    else:
        # No data selected
        row_chunk_sizes = (0,)
    offsets = np.cumsum((0,) + row_chunk_sizes)

    out_chunks = []
    for i, row_size in enumerate(row_chunk_sizes):
        chunk_op = op.copy().reset_key()
        chunk_op._row_memory_usage = None  # no need for chunk
        offset = chunk_op._offset = offsets[i]
        if df.index_value.has_value():
            # range index
            index_value = parse_index(
                df.index_value.to_pandas()[offset : offsets[i + 1]]
            )
        else:
            index_value = parse_index(
                df.index_value.to_pandas(),
                op.table_or_sql or str(op.selectable),
                op.con,
                i,
                row_size,
            )
        out_chunk = chunk_op.new_chunk(
            None,
            shape=(row_size, df.shape[1]),
            columns_value=df.columns_value,
            index_value=index_value,
            dtypes=df.dtypes,
            index=(i, 0),
        )
        out_chunks.append(out_chunk)

    nsplits = (row_chunk_sizes, (df.shape[1],))
    new_op = op.copy()
    return new_op.new_dataframes(None, chunks=out_chunks, nsplits=nsplits, **df.params)


# 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_offset(cls, op: "DataFrameReadSQL"):
    df = op.outputs[0]

    if op.row_memory_usage is not None:
        # Data selected
        chunk_size = df.extra_params.raw_chunk_size or options.chunk_size
        if chunk_size is None:
            chunk_size = (
                int(options.chunk_store_limit / op.row_memory_usage),
                df.shape[1],
            )
        row_chunk_sizes = normalize_chunk_sizes(df.shape, chunk_size)[0]
    else:
        # No data selected
        row_chunk_sizes = (0,)
    offsets = np.cumsum((0,) + row_chunk_sizes).tolist()

    out_chunks = []
    for i, row_size in enumerate(row_chunk_sizes):
        chunk_op = op.copy().reset_key()
        chunk_op._row_memory_usage = None  # no need for chunk
        offset = chunk_op._offset = offsets[i]
        if df.index_value.has_value():
            # range index
            index_value = parse_index(
                df.index_value.to_pandas()[offset : offsets[i + 1]]
            )
        else:
            index_value = parse_index(
                df.index_value.to_pandas(),
                op.table_or_sql or str(op.selectable),
                op.con,
                i,
                row_size,
            )
        out_chunk = chunk_op.new_chunk(
            None,
            shape=(row_size, df.shape[1]),
            columns_value=df.columns_value,
            index_value=index_value,
            dtypes=df.dtypes,
            index=(i, 0),
        )
        out_chunks.append(out_chunk)

    nsplits = (row_chunk_sizes, (df.shape[1],))
    new_op = op.copy()
    return new_op.new_dataframes(None, chunks=out_chunks, nsplits=nsplits, **df.params)