# Buggy code
def execute(cls, ctx, op):
    xdf = cudf if op.gpu else pd
    out_df = op.outputs[0]
    csv_kwargs = op.extra_params.copy()

    with open_file(
        op.path, compression=op.compression, storage_options=op.storage_options
    ) as f:
        if op.compression is not None:
            # As we specify names and dtype, we need to skip header rows
            csv_kwargs["skiprows"] = 1 if op.header == "infer" else op.header
            dtypes = cls._validate_dtypes(op.outputs[0].dtypes, op.gpu)
            if contain_arrow_dtype(dtypes.values()):
                # when keep_default_na is True which is default,
                # will replace null value with np.nan,
                # which will cause failure when converting to arrow string array
                csv_kwargs["keep_default_na"] = False
            df = xdf.read_csv(
                f,
                sep=op.sep,
                names=op.names,
                index_col=op.index_col,
                usecols=op.usecols,
                dtype=dtypes,
                nrows=op.nrows,
                **csv_kwargs,
            )
            if op.keep_usecols_order:
                df = df[op.usecols]
        else:
            df = cls._cudf_read_csv(op) if op.gpu else cls._pandas_read_csv(f, op)

    ctx[out_df.key] = df


# Traceback (ValueError)
In [9]: df = pd.DataFrame({
...:     'col1': np.random.randint(0, 100, (100000,)),
...:     'col2': np.random.choice(['a', 'b', 'c'], (100000,)),
...:     'col3': np.arange(100000)
...: })
...: df.iloc[-100:, :] = pd.NA

In [10]: df.to_csv('test.csv', index=False)

In [11]: md.read_csv('test.csv').execute()
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-11-560f5a720bd9> in <module>
----> 1 md.read_csv('test.csv').execute()

~/Documents/mars_dev/mars/mars/core.py in execute(self, session, **kw)
626
627         if wait:
--> 628             return run()
629         else:
630             thread_executor = ThreadPoolExecutor(1)

~/Documents/mars_dev/mars/mars/core.py in run()
622
623         def run():
--> 624             self.data.execute(session, **kw)
625             return self
626

~/Documents/mars_dev/mars/mars/core.py in execute(self, session, **kw)
373
374         if wait:
--> 375             return run()
376         else:
377             # leverage ThreadPoolExecutor to submit task,

~/Documents/mars_dev/mars/mars/core.py in run()
368         def run():
369             # no more fetch, thus just fire run
--> 370             session.run(self, **kw)
371             # return Tileable or ExecutableTuple itself
372             return self

~/Documents/mars_dev/mars/mars/session.py in run(self, *tileables, **kw)
476         tileables = tuple(mt.tensor(t) if not isinstance(t, (Entity, Base)) else t
477                           for t in tileables)
--> 478         result = self._sess.run(*tileables, **kw)
479
480         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 _inner(*args, **kwargs)
437         def _inner(*args, **kwargs):
438             with self:
--> 439                 return func(*args, **kwargs)
440
441         return _inner

~/Documents/mars_dev/mars/mars/executor.py in execute_tileables(self, tileables, fetch, n_parallel, n_thread, print_progress, mock, compose, name)
876                                    n_parallel=n_parallel or n_thread,
877                                    print_progress=print_progress, mock=mock,
--> 878                                    chunk_result=chunk_result)
879
880                 # update shape of tileable and its chunks whatever it's successful or not

~/Documents/mars_dev/mars/mars/executor.py in execute_graph(self, graph, keys, n_parallel, print_progress, mock, no_intermediate, compose, retval, chunk_result)
688             print_progress=print_progress, mock=mock, mock_max_memory=self._mock_max_memory,
689             fetch_keys=fetch_keys, no_intermediate=no_intermediate)
--> 690         res = graph_execution.execute(retval)
691         self._mock_max_memory = max(self._mock_max_memory, graph_execution._mock_max_memory)
692         if mock:

~/Documents/mars_dev/mars/mars/executor.py in execute(self, retval)
569         # wait until all the futures completed
570         for future in executed_futures:
--> 571             future.result()
572
573         if retval:

~/miniconda3/envs/py3.7.2/lib/python3.7/concurrent/futures/_base.py in result(self, timeout)
430                 raise CancelledError()
431             elif self._state == FINISHED:
--> 432                 return self.__get_result()
433             else:
434                 raise TimeoutError()

~/miniconda3/envs/py3.7.2/lib/python3.7/concurrent/futures/_base.py in __get_result(self)
382     def __get_result(self):
383         if self._exception:
--> 384             raise self._exception
385         else:
386             return self._result

~/miniconda3/envs/py3.7.2/lib/python3.7/concurrent/futures/thread.py in run(self)
55
56         try:
---> 57             result = self.fn(*self.args, **self.kwargs)
58         except BaseException as exc:
59             self.future.set_exception(exc)

~/Documents/mars_dev/mars/mars/utils.py in _inner(*args, **kwargs)
437         def _inner(*args, **kwargs):
438             with self:
--> 439                 return func(*args, **kwargs)
440
441         return _inner

~/Documents/mars_dev/mars/mars/executor.py in _execute_operand(self, op)
441             # so we pass the first operand's first output to Executor.handle
442             first_op = ops[0]
--> 443             Executor.handle(first_op, results, self._mock)
444
445             # update maximal memory usage during execution

~/Documents/mars_dev/mars/mars/executor.py in handle(cls, op, results, mock)
639                 # The `UFuncTypeError` was introduced by numpy#12593 since v1.17.0.
640                 try:
--> 641                     return runner(results, op)
642                 except UFuncTypeError as e:
643                     raise TypeError(str(e)).with_traceback(sys.exc_info()[2]) from None

~/Documents/mars_dev/mars/mars/dataframe/datasource/read_csv.py in execute(cls, ctx, op)
321                     df = df[op.usecols]
322             else:
--> 323                 df = cls._cudf_read_csv(op) if op.gpu else cls._pandas_read_csv(f, op)
324
325         ctx[out_df.key] = df

~/Documents/mars_dev/mars/mars/dataframe/datasource/read_csv.py in _pandas_read_csv(cls, f, op)
272                 csv_kwargs['keep_default_na'] = False
273             df = pd.read_csv(b, sep=op.sep, names=op.names, index_col=op.index_col, usecols=usecols,
--> 274                              dtype=dtypes.to_dict(), nrows=op.nrows, **csv_kwargs)
275             if op.keep_usecols_order:
276                 df = df[op.usecols]

~/miniconda3/envs/py3.7.2/lib/python3.7/site-packages/pandas/io/parsers.py in parser_f(filepath_or_buffer, sep, delimiter, header, names, index_col, usecols, squeeze, prefix, mangle_dupe_cols, dtype, engine, converters, true_values, false_values, skipinitialspace, skiprows, skipfooter, nrows, na_values, keep_default_na, na_filter, verbose, skip_blank_lines, parse_dates, infer_datetime_format, keep_date_col, date_parser, dayfirst, cache_dates, iterator, chunksize, compression, thousands, decimal, lineterminator, quotechar, quoting, doublequote, escapechar, comment, encoding, dialect, error_bad_lines, warn_bad_lines, delim_whitespace, low_memory, memory_map, float_precision)
674         )
675
--> 676         return _read(filepath_or_buffer, kwds)
677
678     parser_f.__name__ = name

~/miniconda3/envs/py3.7.2/lib/python3.7/site-packages/pandas/io/parsers.py in _read(filepath_or_buffer, kwds)
452
453     try:
--> 454         data = parser.read(nrows)
455     finally:
456         parser.close()

~/miniconda3/envs/py3.7.2/lib/python3.7/site-packages/pandas/io/parsers.py in read(self, nrows)
1131     def read(self, nrows=None):
1132         nrows = _validate_integer("nrows", nrows)
-> 1133         ret = self._engine.read(nrows)
1134
1135         # May alter columns / col_dict

~/miniconda3/envs/py3.7.2/lib/python3.7/site-packages/pandas/io/parsers.py in read(self, nrows)
2035     def read(self, nrows=None):
2036         try:
-> 2037             data = self._reader.read(nrows)
2038         except StopIteration:
2039             if self._first_chunk:

pandas/_libs/parsers.pyx in pandas._libs.parsers.TextReader.read()

pandas/_libs/parsers.pyx in pandas._libs.parsers.TextReader._read_low_memory()

pandas/_libs/parsers.pyx in pandas._libs.parsers.TextReader._read_rows()

pandas/_libs/parsers.pyx in pandas._libs.parsers.TextReader._convert_column_data()

pandas/_libs/parsers.pyx in pandas._libs.parsers.TextReader._convert_tokens()

pandas/_libs/parsers.pyx in pandas._libs.parsers.TextReader._convert_with_dtype()

ValueError: Integer column has NA values in column 0

# Fixed code
def execute(cls, ctx, op):
    xdf = cudf if op.gpu else pd
    out_df = op.outputs[0]
    csv_kwargs = op.extra_params.copy()

    with open_file(
        op.path, compression=op.compression, storage_options=op.storage_options
    ) as f:
        if op.compression is not None:
            # As we specify names and dtype, we need to skip header rows
            csv_kwargs["skiprows"] = 1 if op.header == "infer" else op.header
            dtypes = op.outputs[0].dtypes
            if contain_arrow_dtype(dtypes):
                # when keep_default_na is True which is default,
                # will replace null value with np.nan,
                # which will cause failure when converting to arrow string array
                csv_kwargs["keep_default_na"] = False
                csv_kwargs["dtype"] = cls._select_arrow_dtype(dtypes)
            df = xdf.read_csv(
                f,
                sep=op.sep,
                names=op.names,
                index_col=op.index_col,
                usecols=op.usecols,
                nrows=op.nrows,
                **csv_kwargs,
            )
            if op.keep_usecols_order:
                df = df[op.usecols]
        else:
            df = cls._cudf_read_csv(op) if op.gpu else cls._pandas_read_csv(f, op)

    ctx[out_df.key] = df