# Buggy code
def _read_csv_from_file_pandas_on_ray(cls, filepath, kwargs={}):
    """Constructs a DataFrame from a CSV file.

    Args:
        filepath (str): path to the CSV file.
        npartitions (int): number of partitions for the DataFrame.
        kwargs (dict): args excluding filepath provided to read_csv.

    Returns:
        DataFrame or Series constructed from CSV file.
    """
    empty_pd_df = pandas.read_csv(filepath, **dict(kwargs, nrows=0, skipfooter=0))
    column_names = empty_pd_df.columns
    skipfooter = kwargs.get("skipfooter", None)
    skiprows = kwargs.pop("skiprows", None)
    partition_kwargs = dict(
        kwargs, header=None, names=column_names, skipfooter=0, skiprows=None
    )
    with open(filepath, "rb") as f:
        # Get the BOM if necessary
        prefix = b""
        if kwargs.get("encoding", None) is not None:
            prefix = f.readline()
            partition_kwargs["skiprows"] = 1
            f.seek(0, os.SEEK_SET)  # Return to beginning of file

        prefix_id = ray.put(prefix)
        partition_kwargs_id = ray.put(partition_kwargs)
        # Skip the header since we already have the header information and skip the
        # rows we are told to skip.
        kwargs["skiprows"] = skiprows
        cls._skip_header(f, kwargs)
        # Launch tasks to read partitions
        partition_ids = []
        index_ids = []
        total_bytes = os.path.getsize(filepath)
        # Max number of partitions available
        num_parts = RayBlockPartitions._compute_num_partitions()
        # This is the number of splits for the columns
        num_splits = min(len(column_names), num_parts)
        # This is the chunksize each partition will read
        chunk_size = max(1, (total_bytes - f.tell()) // num_parts)

        while f.tell() < total_bytes:
            start = f.tell()
            f.seek(chunk_size, os.SEEK_CUR)
            f.readline()  # Read a whole number of lines
            partition_id = _read_csv_with_offset_pandas_on_ray._remote(
                args=(
                    filepath,
                    num_splits,
                    start,
                    f.tell(),
                    partition_kwargs_id,
                    prefix_id,
                ),
                num_return_vals=num_splits + 1,
            )
            partition_ids.append(
                [PandasOnRayRemotePartition(obj) for obj in partition_id[:-1]]
            )
            index_ids.append(partition_id[-1])

    index_col = kwargs.get("index_col", None)
    if index_col is None:
        new_index = pandas.RangeIndex(sum(ray.get(index_ids)))
    else:
        new_index_ids = get_index.remote([empty_pd_df.index.name], *index_ids)
        new_index = ray.get(new_index_ids)

    new_query_compiler = PandasQueryCompiler(
        RayBlockPartitions(np.array(partition_ids)), new_index, column_names
    )

    if skipfooter:
        new_query_compiler = new_query_compiler.drop(
            new_query_compiler.index[-skipfooter:]
        )
    if kwargs.get("squeeze", False) and len(new_query_compiler.columns) == 1:
        return new_query_compiler[new_query_compiler.columns[0]]
    return new_query_compiler


# Traceback (Exception)
import modin.pandas as pd

with open('test.tsv', 'w') as f:
f.write("Date\tTime\n"
"7/12/2018\t16:29:42.27\n"
"7/12/2018\t16:30:11.83")

pd.read_csv('test.tsv', sep='\t',
parse_dates={'timestamp':['Date', 'Time']})

---------------------------------------------------------------------------
Exception                                 Traceback (most recent call last)
/usr/local/lib/python3.5/dist-packages/IPython/core/formatters.py in __call__(self, obj)
700                 type_pprinters=self.type_printers,
701                 deferred_pprinters=self.deferred_printers)
--> 702             printer.pretty(obj)
703             printer.flush()
704             return stream.getvalue()

/usr/local/lib/python3.5/dist-packages/IPython/lib/pretty.py in pretty(self, obj)
398                         if cls is not object \
399                                 and callable(cls.__dict__.get('__repr__')):
--> 400                             return _repr_pprint(obj, self, cycle)
401
402             return _default_pprint(obj, self, cycle)

/usr/local/lib/python3.5/dist-packages/IPython/lib/pretty.py in _repr_pprint(obj, p, cycle)
693     """A pprint that just redirects to the normal repr function."""
694     # Find newlines and replace them with p.break_()
--> 695     output = repr(obj)
696     for idx,output_line in enumerate(output.splitlines()):
697         if idx:

~/.local/lib/python3.5/site-packages/modin/pandas/dataframe.py in __repr__(self)
124         num_cols = 30
125
--> 126         result = repr(self._build_repr_df(num_rows, num_cols))
127         if len(self.index) > num_rows or len(self.columns) > num_cols:
128             # The split here is so that we don't repr pandas row lengths.

~/.local/lib/python3.5/site-packages/modin/pandas/dataframe.py in _build_repr_df(self, num_rows, num_cols)
95
96         if len(self.columns) <= num_cols:
---> 97             head_front = head.to_pandas()
98             # Creating these empty to make the concat logic simpler
99             head_back = pandas.DataFrame()

~/.local/lib/python3.5/site-packages/modin/data_management/query_compiler/pandas_query_compiler.py in to_pandas(self)
2197         else:
2198             ErrorMessage.catch_bugs_and_request_email(
-> 2199                 len(df.index) != len(self.index) or len(df.columns) != len(self.columns)
2200             )
2201             df.index = self.index

~/.local/lib/python3.5/site-packages/modin/error_message.py in catch_bugs_and_request_email(cls, failure_condition)
36         if failure_condition:
37             raise Exception(
---> 38                 "Internal Error. "
39                 "Please email bug_reports@modin.org with the traceback and command that"
40                 " caused this error."

Exception: Internal Error. Please email bug_reports@modin.org with the traceback and command that caused this error.

# Fixed code
def _read_csv_from_file_pandas_on_ray(cls, filepath, kwargs={}):
    """Constructs a DataFrame from a CSV file.

    Args:
        filepath (str): path to the CSV file.
        npartitions (int): number of partitions for the DataFrame.
        kwargs (dict): args excluding filepath provided to read_csv.

    Returns:
        DataFrame or Series constructed from CSV file.
    """
    empty_pd_df = pandas.read_csv(filepath, **dict(kwargs, nrows=0, skipfooter=0))
    column_names = empty_pd_df.columns
    skipfooter = kwargs.get("skipfooter", None)
    skiprows = kwargs.pop("skiprows", None)
    parse_dates = kwargs.pop("parse_dates", False)
    partition_kwargs = dict(
        kwargs,
        header=None,
        names=column_names,
        skipfooter=0,
        skiprows=None,
        parse_dates=parse_dates,
    )
    with open(filepath, "rb") as f:
        # Get the BOM if necessary
        prefix = b""
        if kwargs.get("encoding", None) is not None:
            prefix = f.readline()
            partition_kwargs["skiprows"] = 1
            f.seek(0, os.SEEK_SET)  # Return to beginning of file

        prefix_id = ray.put(prefix)
        partition_kwargs_id = ray.put(partition_kwargs)
        # Skip the header since we already have the header information and skip the
        # rows we are told to skip.
        kwargs["skiprows"] = skiprows
        cls._skip_header(f, kwargs)
        # Launch tasks to read partitions
        partition_ids = []
        index_ids = []
        total_bytes = os.path.getsize(filepath)
        # Max number of partitions available
        num_parts = RayBlockPartitions._compute_num_partitions()
        # This is the number of splits for the columns
        num_splits = min(len(column_names), num_parts)
        # This is the chunksize each partition will read
        chunk_size = max(1, (total_bytes - f.tell()) // num_parts)

        while f.tell() < total_bytes:
            start = f.tell()
            f.seek(chunk_size, os.SEEK_CUR)
            f.readline()  # Read a whole number of lines
            partition_id = _read_csv_with_offset_pandas_on_ray._remote(
                args=(
                    filepath,
                    num_splits,
                    start,
                    f.tell(),
                    partition_kwargs_id,
                    prefix_id,
                ),
                num_return_vals=num_splits + 1,
            )
            partition_ids.append(
                [PandasOnRayRemotePartition(obj) for obj in partition_id[:-1]]
            )
            index_ids.append(partition_id[-1])

    index_col = kwargs.get("index_col", None)
    if index_col is None:
        new_index = pandas.RangeIndex(sum(ray.get(index_ids)))
    else:
        new_index_ids = get_index.remote([empty_pd_df.index.name], *index_ids)
        new_index = ray.get(new_index_ids)

    # If parse_dates is present, the column names that we have might not be
    # the same length as the returned column names. If we do need to modify
    # the column names, we remove the old names from the column names and
    # insert the new one at the front of the Index.
    if parse_dates is not None:
        # Check if is list of lists
        if isinstance(parse_dates, list) and isinstance(parse_dates[0], list):
            for group in parse_dates:
                new_col_name = "_".join(group)
                column_names = column_names.drop(group).insert(0, new_col_name)
        # Check if it is a dictionary
        elif isinstance(parse_dates, dict):
            for new_col_name, group in parse_dates.items():
                column_names = column_names.drop(group).insert(0, new_col_name)

    new_query_compiler = PandasQueryCompiler(
        RayBlockPartitions(np.array(partition_ids)), new_index, column_names
    )

    if skipfooter:
        new_query_compiler = new_query_compiler.drop(
            new_query_compiler.index[-skipfooter:]
        )
    if kwargs.get("squeeze", False) and len(new_query_compiler.columns) == 1:
        return new_query_compiler[new_query_compiler.columns[0]]
    return new_query_compiler