# Buggy code
def execute(cls, ctx, op):
    (a, b), device_id, xp = as_same_device(
        [ctx[c.key] for c in op.inputs], device=op.device, ret_extra=True
    )

    with device(device_id):
        if not op.sparse and is_sparse_module(xp):
            # tell sparse to do calculation on numpy or cupy matmul
            ctx[op.outputs[0].key] = xp.matmul(a, b, sparse=False)
        else:
            ctx[op.outputs[0].key] = xp.matmul(a, b, casting=op.casting, order=op.order)


# Traceback (InvalidComposedNodeError)
In [1]: import mars.tensor as mt

In [2]: a = mt.random.rand(4, 4) + 1 - 3

In [3]: u, s, v = mt.linalg.svd(a)

In [4]: (u + 1).execute()
Out[4]:
array([[0.53491564, 0.50844154, 1.31934217, 0.33660917],
[0.48043745, 0.58359388, 1.12894514, 1.73486995],
[0.54248881, 1.05235106, 0.12344775, 0.86000348],
[0.4482439 , 1.76304364, 1.33622891, 0.98327479]])

In [5]: (u + 2).execute()
---------------------------------------------------------------------------
InvalidComposedNodeError                  Traceback (most recent call last)
<ipython-input-5-1dd2365be547> in <module>
----> 1 (u + 2).execute()

~/Documents/mars_dev/mars/mars/tensor/core.py in execute(self, session, **kw)
442
443     def execute(self, session=None, **kw):
--> 444         return self._data.execute(session, **kw)
445
446

~/Documents/mars_dev/mars/mars/core.py in execute(self, session, **kw)
572         if session is None:
573             session = Session.default_or_local()
--> 574         return session.run(self, **kw)
575
576     def fetch(self, session=None, **kw):

~/Documents/mars_dev/mars/mars/session.py in run(self, *tileables, **kw)
150         tileables = tuple(mt.tensor(t) if not isinstance(t, (Entity, Base)) else t
151                           for t in tileables)
--> 152         result = self._sess.run(*tileables, **kw)
153
154         for t in tileables:

~/Documents/mars_dev/mars/mars/session.py in run(self, *tileables, **kw)
61         if 'n_parallel' not in kw:
62             kw['n_parallel'] = cpu_count()
---> 63         res = self._executor.execute_tileables(tileables, **kw)
64         return res
65

~/Documents/mars_dev/mars/mars/utils.py in _wrapped(*args, **kwargs)
389                 _kernel_mode.eager = False
390             _kernel_mode.eager_count = enter_eager_count + 1
--> 391             return func(*args, **kwargs)
392         finally:
393             _kernel_mode.eager_count -= 1

~/Documents/mars_dev/mars/mars/executor.py in execute_tileables(self, tileables, fetch, n_parallel, n_thread, print_progress, mock, compose)
548
549         self.execute_graph(graph, result_keys, n_parallel=n_parallel or n_thread,
--> 550                            print_progress=print_progress, mock=mock)
551
552         results = self._chunk_result

~/Documents/mars_dev/mars/mars/executor.py in execute_graph(self, graph, keys, n_parallel, print_progress, mock, no_intermediate, compose, retval)
469         :return: execution result
470         """
--> 471         optimized_graph = self._preprocess(graph, keys) if compose else graph
472
473         if not mock:

~/Documents/mars_dev/mars/mars/executor.py in _preprocess(self, graph, keys)
435         from .optimizes.core import Optimizer
436
--> 437         Optimizer(graph, self._engine).optimize(keys=keys)
438         return graph
439

~/Documents/mars_dev/mars/mars/optimizes/core.py in optimize(self, keys)
32
33     def optimize(self, keys=None):
---> 34         self._graph.decompose()
35         if self._engine == 'numpy':
36             return

~/Documents/mars_dev/mars/mars/graph.pyx in mars.graph.DirectedGraph.decompose()

~/Documents/mars_dev/mars/mars/fuse.pyx in mars.fuse.Fusion.decompose()

~/Documents/mars_dev/mars/mars/fuse.pyx in mars.fuse.Fusion._decompose_node()

InvalidComposedNodeError: Invalid composed node data

# Fixed code
def execute(cls, ctx, op):
    (a, b), device_id, xp = as_same_device(
        [ctx[c.key] for c in op.inputs], device=op.device, ret_extra=True
    )

    with device(device_id):
        if not op.sparse and is_sparse_module(xp):
            # tell sparse to do calculation on numpy or cupy matmul
            ctx[op.outputs[0].key] = xp.matmul(a, b, sparse=False)
        else:
            try:
                # `np.matmul` support `order` argument in version 1.16
                ctx[op.outputs[0].key] = xp.matmul(
                    a, b, casting=op.casting, order=op.order
                )
            except TypeError:  # pragma: no cover
                ctx[op.outputs[0].key] = xp.matmul(a, b).astype(
                    dtype=op.dtype, casting=op.casting, order=op.order
                )