# Buggy code
def fetch_tensors(self, tensors, **kw):
    from .tensor.expressions.fetch import TensorFetch

    results = []
    to_concat_tensors = OrderedDict()

    for i, tensor in enumerate(tensors):
        if tensor.key not in self.stored_tensors:
            # check if the tensor is executed before
            raise ValueError(
                "Tensor to fetch must be executed before, got {0}".format(tensor)
            )

        if len(tensor.chunks) == 1:
            result = self._chunk_result[tensor.chunks[0].key]
            results.append(result)
            continue

        # generate TensorFetch op for each chunk
        chunks = []
        for c in tensor.chunks:
            op = TensorFetch(dtype=c.dtype)
            chunk = op.new_chunk(None, c.shape, index=c.index, _key=c.key)
            chunks.append(chunk)

        new_op = TensorFetch(dtype=tensor.dtype)
        # copy key and id to ensure that fetch tensor won't add the count of executed tensor
        tensor = new_op.new_tensor(
            None,
            tensor.shape,
            chunks=chunks,
            nsplits=tensor.nsplits,
            _key=tensor.key,
            _id=tensor.id,
        )

        # add this concat tensor into the list which shall be executed later
        to_concat_tensors[i] = tensor
        results.append(None)

    # execute the concat tensors together
    if to_concat_tensors:
        concat_results = self.execute_tensors(list(to_concat_tensors.values()), **kw)
        for j, concat_result in zip(to_concat_tensors, concat_results):
            results[j] = concat_result

    return results


# Traceback (mars.error)
In [1]: from mars.deploy.local import new_cluster

In [2]: cluster = new_cluster(scheduler_n_process=2, worker_n_process=3, shared_memory='20M',)

In [3]: import mars.tensor as mt

In [4]: import scipy.sparse as sps

In [5]: a = sps.csr_matrix((10000, 10000))

In [6]: b = sps.csr_matrix((10000, 1))

In [7]: t1 = mt.tensor(a)

In [8]: t2 = mt.tensor(b)


In [9]: from mars.session import new_session

In [10]: cluster.session.run(t1 * t2)

Unexpected exception occurred in ChunkHolderActor.spill_size.
Traceback (most recent call last):
File "/Users/hekaisheng/Documents/mars_dev/mars/mars/utils.py", line 298, in _wrapped
return func(*args, **kwargs)
File "/Users/hekaisheng/Documents/mars_dev/mars/mars/worker/chunkholder.py", line 123, in spill_size
raise SpillExhausted
mars.errors.SpillExhausted
Unhandled exception in promise call
Traceback (most recent call last):
File "/Users/hekaisheng/Documents/mars_dev/mars/mars/promise.py", line 304, in _wrapped
return func(*args, **kwargs)
File "/Users/hekaisheng/Documents/mars_dev/mars/mars/utils.py", line 298, in _wrapped
return func(*args, **kwargs)
File "/Users/hekaisheng/Documents/mars_dev/mars/mars/worker/chunkholder.py", line 123, in spill_size
raise SpillExhausted
mars.errors.SpillExhausted
....

# Fixed code
def fetch_tensors(self, tensors, **kw):
    from .tensor.expressions.fetch import TensorFetch

    results = []
    to_concat_tensors = OrderedDict()

    for i, tensor in enumerate(tensors):
        if tensor.key not in self.stored_tensors:
            # check if the tensor is executed before
            raise ValueError(
                "Tensor to fetch must be executed before, got {0}".format(tensor)
            )

        if len(tensor.chunks) == 1:
            result = self._chunk_result[tensor.chunks[0].key]
            results.append(result)
            continue

        # generate TensorFetch op for each chunk
        chunks = []
        for c in tensor.chunks:
            op = TensorFetch(dtype=c.dtype, sparse=c.op.sparse)
            chunk = op.new_chunk(None, c.shape, index=c.index, _key=c.key)
            chunks.append(chunk)

        new_op = TensorFetch(dtype=tensor.dtype, sparse=tensor.op.sparse)
        # copy key and id to ensure that fetch tensor won't add the count of executed tensor
        tensor = new_op.new_tensor(
            None,
            tensor.shape,
            chunks=chunks,
            nsplits=tensor.nsplits,
            _key=tensor.key,
            _id=tensor.id,
        )

        # add this concat tensor into the list which shall be executed later
        to_concat_tensors[i] = tensor
        results.append(None)

    # execute the concat tensors together
    if to_concat_tensors:
        concat_results = self.execute_tensors(list(to_concat_tensors.values()), **kw)
        for j, concat_result in zip(to_concat_tensors, concat_results):
            results[j] = concat_result

    return results