# Buggy code
def tile(cls, op: "DataFrameToCSV"):
    in_df = op.input
    out_df = op.outputs[0]

    if in_df.ndim == 2:
        # make sure only 1 chunk on the column axis
        in_df = in_df.rechunk({1: in_df.shape[1]})._inplace_tile()

    one_file = op.one_file

    out_chunks = [], []
    for chunk in in_df.chunks:
        chunk_op = op.copy().reset_key()
        if not one_file:
            index_value = parse_index(chunk.index_value.to_pandas()[:0], chunk)
            if chunk.ndim == 2:
                out_chunk = chunk_op.new_chunk(
                    [chunk],
                    shape=(0, 0),
                    index_value=index_value,
                    columns_value=out_df.columns_value,
                    dtypes=out_df.dtypes,
                    index=chunk.index,
                )
            else:
                out_chunk = chunk_op.new_chunk(
                    [chunk],
                    shape=(0,),
                    index_value=index_value,
                    dtype=out_df.dtype,
                    index=chunk.index,
                )
            out_chunks[0].append(out_chunk)
        else:
            chunk_op._output_stat = True
            chunk_op._stage = OperandStage.map
            # bytes of csv
            kws = [
                {
                    "shape": (),
                    "dtype": np.dtype(np.str_),
                    "index": chunk.index,
                    "order": TensorOrder.C_ORDER,
                    "output_type": OutputType.scalar,
                    "type": "csv",
                },
                {
                    "shape": (),
                    "dtype": np.dtype(np.intp),
                    "index": chunk.index,
                    "order": TensorOrder.C_ORDER,
                    "output_type": OutputType.scalar,
                    "type": "stat",
                },
            ]
            chunks = chunk_op.new_chunks([chunk], kws=kws, output_limit=len(kws))
            out_chunks[0].append(chunks[0])
            out_chunks[1].append(chunks[1])

    if not one_file:
        out_chunks = out_chunks[0]
    else:
        stat_chunk = DataFrameToCSVStat(
            path=op.path, dtype=np.dtype(np.int64), storage_options=op.storage_options
        ).new_chunk(
            out_chunks[1], shape=(len(out_chunks[0]),), order=TensorOrder.C_ORDER
        )
        new_out_chunks = []
        for c in out_chunks[0]:
            op = DataFrameToCSV(
                stage=OperandStage.agg,
                path=op.path,
                storage_options=op.storage_options,
                output_types=op.output_types,
            )
            if out_df.ndim == 2:
                out_chunk = op.new_chunk(
                    [c, stat_chunk],
                    shape=(0, 0),
                    dtypes=out_df.dtypes,
                    index_value=out_df.index_value,
                    columns_value=out_df.columns_value,
                    index=c.index,
                )
            else:
                out_chunk = op.new_chunk(
                    [c, stat_chunk],
                    shape=(0,),
                    dtype=out_df.dtype,
                    index_value=out_df.index_value,
                    index=c.index,
                )
            new_out_chunks.append(out_chunk)
        out_chunks = new_out_chunks

    new_op = op.copy()
    params = out_df.params.copy()
    if out_df.ndim == 2:
        params.update(
            dict(chunks=out_chunks, nsplits=((0,) * in_df.chunk_shape[0], (0,)))
        )
    else:
        params.update(dict(chunks=out_chunks, nsplits=((0,) * in_df.chunk_shape[0],)))
    return new_op.new_tileables([in_df], **params)


# Traceback (ValueError)
Traceback (most recent call last):
File "/home/admin/work/_public-mars-0.6.2.zip/mars/scheduler/graph.py", line 410, in _execute_graph
self.prepare_graph(compose=compose)
File "/home/admin/work/_public-mars-0.6.2.zip/mars/utils.py", line 377, in _wrapped
return func(*args, **kwargs)
File "/home/admin/work/_public-mars-0.6.2.zip/mars/utils.py", line 451, in _inner
return func(*args, **kwargs)
File "/home/admin/work/_public-mars-0.6.2.zip/mars/scheduler/graph.py", line 648, in prepare_graph
self._target_tileable_datas + fetch_tileables, tileable_graph)
File "/home/admin/work/_public-mars-0.6.2.zip/mars/utils.py", line 451, in _inner
return func(*args, **kwargs)
File "/home/admin/work/_public-mars-0.6.2.zip/mars/tiles.py", line 348, in build
tileables, tileable_graph=tileable_graph)
File "/home/admin/work/_public-mars-0.6.2.zip/mars/utils.py", line 451, in _inner
return func(*args, **kwargs)
File "/home/admin/work/_public-mars-0.6.2.zip/mars/tiles.py", line 262, in build
self._on_tile_failure(tileable_data.op, exc_info)
File "/home/admin/work/_public-mars-0.6.2.zip/mars/tiles.py", line 301, in inner
raise exc_info[1].with_traceback(exc_info[2]) from None
File "/home/admin/work/_public-mars-0.6.2.zip/mars/tiles.py", line 242, in build
tiled = self._tile(tileable_data, tileable_graph)
File "/home/admin/work/_public-mars-0.6.2.zip/mars/tiles.py", line 337, in _tile
return super()._tile(tileable_data, tileable_graph)
File "/home/admin/work/_public-mars-0.6.2.zip/mars/tiles.py", line 203, in _tile
tds = on_tile(tileable_data.op.outputs, tds)
File "/home/admin/work/_public-mars-0.6.2.zip/mars/scheduler/graph.py", line 630, in on_tile
return self.context.wraps(handler.dispatch)(first.op)
File "/home/admin/work/_public-mars-0.6.2.zip/mars/context.py", line 72, in h
return func(*args, **kwargs)
File "/home/admin/work/_public-mars-0.6.2.zip/mars/utils.py", line 451, in _inner
return func(*args, **kwargs)
File "/home/admin/work/_public-mars-0.6.2.zip/mars/tiles.py", line 119, in dispatch
tiled = op_cls.tile(op)
File "/home/admin/work/_public-mars-0.6.2.zip/mars/learn/contrib/xgboost/dmatrix.py", line 255, in tile
return cls._tile_multi_output(op)
File "/home/admin/work/_public-mars-0.6.2.zip/mars/learn/contrib/xgboost/dmatrix.py", line 139, in _tile_multi_output
label = label.rechunk({0: nsplit})._inplace_tile()
File "/home/admin/work/_public-mars-0.6.2.zip/mars/tensor/rechunk/rechunk.py", line 81, in rechunk
chunk_size = get_nsplits(tensor, chunk_size, tensor.dtype.itemsize)
File "/home/admin/work/_public-mars-0.6.2.zip/mars/tensor/rechunk/core.py", line 38, in get_nsplits
return decide_chunk_sizes(tileable.shape, chunk_size, itemsize)
File "/home/admin/work/_public-mars-0.6.2.zip/mars/tensor/utils.py", line 551, in decide_chunk_sizes
return normalize_chunk_sizes(shape, tuple(chunk_size[j] for j in range(len(shape))))
File "/home/admin/work/_public-mars-0.6.2.zip/mars/tensor/utils.py", line 66, in normalize_chunk_sizes
raise ValueError('chunks shape should be of the same length, '
ValueError: chunks shape should be of the same length, got shape: 1000000, chunks: (nan,)

# Fixed code
def tile(cls, op: "DataFrameToCSV"):
    in_df = op.input
    out_df = op.outputs[0]

    if in_df.ndim == 2 and in_df.chunk_shape[1] > 1:
        # make sure only 1 chunk on the column axis
        in_df = in_df.rechunk({1: in_df.shape[1]})._inplace_tile()

    one_file = op.one_file

    out_chunks = [], []
    for chunk in in_df.chunks:
        chunk_op = op.copy().reset_key()
        if not one_file:
            index_value = parse_index(chunk.index_value.to_pandas()[:0], chunk)
            if chunk.ndim == 2:
                out_chunk = chunk_op.new_chunk(
                    [chunk],
                    shape=(0, 0),
                    index_value=index_value,
                    columns_value=out_df.columns_value,
                    dtypes=out_df.dtypes,
                    index=chunk.index,
                )
            else:
                out_chunk = chunk_op.new_chunk(
                    [chunk],
                    shape=(0,),
                    index_value=index_value,
                    dtype=out_df.dtype,
                    index=chunk.index,
                )
            out_chunks[0].append(out_chunk)
        else:
            chunk_op._output_stat = True
            chunk_op._stage = OperandStage.map
            # bytes of csv
            kws = [
                {
                    "shape": (),
                    "dtype": np.dtype(np.str_),
                    "index": chunk.index,
                    "order": TensorOrder.C_ORDER,
                    "output_type": OutputType.scalar,
                    "type": "csv",
                },
                {
                    "shape": (),
                    "dtype": np.dtype(np.intp),
                    "index": chunk.index,
                    "order": TensorOrder.C_ORDER,
                    "output_type": OutputType.scalar,
                    "type": "stat",
                },
            ]
            chunks = chunk_op.new_chunks([chunk], kws=kws, output_limit=len(kws))
            out_chunks[0].append(chunks[0])
            out_chunks[1].append(chunks[1])

    if not one_file:
        out_chunks = out_chunks[0]
    else:
        stat_chunk = DataFrameToCSVStat(
            path=op.path, dtype=np.dtype(np.int64), storage_options=op.storage_options
        ).new_chunk(
            out_chunks[1], shape=(len(out_chunks[0]),), order=TensorOrder.C_ORDER
        )
        new_out_chunks = []
        for c in out_chunks[0]:
            op = DataFrameToCSV(
                stage=OperandStage.agg,
                path=op.path,
                storage_options=op.storage_options,
                output_types=op.output_types,
            )
            if out_df.ndim == 2:
                out_chunk = op.new_chunk(
                    [c, stat_chunk],
                    shape=(0, 0),
                    dtypes=out_df.dtypes,
                    index_value=out_df.index_value,
                    columns_value=out_df.columns_value,
                    index=c.index,
                )
            else:
                out_chunk = op.new_chunk(
                    [c, stat_chunk],
                    shape=(0,),
                    dtype=out_df.dtype,
                    index_value=out_df.index_value,
                    index=c.index,
                )
            new_out_chunks.append(out_chunk)
        out_chunks = new_out_chunks

    new_op = op.copy()
    params = out_df.params.copy()
    if out_df.ndim == 2:
        params.update(
            dict(chunks=out_chunks, nsplits=((0,) * in_df.chunk_shape[0], (0,)))
        )
    else:
        params.update(dict(chunks=out_chunks, nsplits=((0,) * in_df.chunk_shape[0],)))
    return new_op.new_tileables([in_df], **params)