# Buggy code
def _make_concat_multiindex(indexes, keys, levels=None, names=None) -> MultiIndex:
    if (levels is None and isinstance(keys[0], tuple)) or (
        levels is not None and len(levels) > 1
    ):
        zipped = list(zip(*keys))
        if names is None:
            names = [None] * len(zipped)

        if levels is None:
            _, levels = factorize_from_iterables(zipped)
        else:
            levels = [ensure_index(x) for x in levels]
    else:
        zipped = [keys]
        if names is None:
            names = [None]

        if levels is None:
            levels = [ensure_index(keys)]
        else:
            levels = [ensure_index(x) for x in levels]

    if not all_indexes_same(indexes):
        codes_list = []

        # things are potentially different sizes, so compute the exact codes
        # for each level and pass those to MultiIndex.from_arrays

        for hlevel, level in zip(zipped, levels):
            to_concat = []
            for key, index in zip(hlevel, indexes):
                try:
                    i = level.get_loc(key)
                except KeyError as err:
                    raise ValueError(f"Key {key} not in level {level}") from err

                to_concat.append(np.repeat(i, len(index)))
            codes_list.append(np.concatenate(to_concat))

        concat_index = _concat_indexes(indexes)

        # these go at the end
        if isinstance(concat_index, MultiIndex):
            levels.extend(concat_index.levels)
            codes_list.extend(concat_index.codes)
        else:
            codes, categories = factorize_from_iterable(concat_index)
            levels.append(categories)
            codes_list.append(codes)

        if len(names) == len(levels):
            names = list(names)
        else:
            # make sure that all of the passed indices have the same nlevels
            if not len({idx.nlevels for idx in indexes}) == 1:
                raise AssertionError(
                    "Cannot concat indices that do not have the same number of levels"
                )

            # also copies
            names = names + get_consensus_names(indexes)

        return MultiIndex(
            levels=levels, codes=codes_list, names=names, verify_integrity=False
        )

    new_index = indexes[0]
    n = len(new_index)
    kpieces = len(indexes)

    # also copies
    new_names = list(names)
    new_levels = list(levels)

    # construct codes
    new_codes = []

    # do something a bit more speedy

    for hlevel, level in zip(zipped, levels):
        hlevel = ensure_index(hlevel)
        mapped = level.get_indexer(hlevel)

        mask = mapped == -1
        if mask.any():
            raise ValueError(f"Values not found in passed level: {hlevel[mask]!s}")

        new_codes.append(np.repeat(mapped, n))

    if isinstance(new_index, MultiIndex):
        new_levels.extend(new_index.levels)
        new_codes.extend([np.tile(lab, kpieces) for lab in new_index.codes])
    else:
        new_levels.append(new_index)
        new_codes.append(np.tile(np.arange(n), kpieces))

    if len(new_names) < len(new_levels):
        new_names.extend(new_index.names)

    return MultiIndex(
        levels=new_levels, codes=new_codes, names=new_names, verify_integrity=False
    )


# Traceback (TypeError)
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-2-f6a5f4790f76> in <module>
3 s1 = pd.Series([1,2,3], name='a')
4 s2 = pd.Series([1,2,3], name='a')
----> 5 pd.concat([df, s1, s2], axis=1, keys=['a', 'b', 'b'])

~/pandas-dev/pandas/core/reshape/concat.py in concat(objs, axis, join, ignore_index, keys, levels, names, verify_integrity, sort, copy)
269     ValueError: Indexes have overlapping values: ['a']
270     """
--> 271     op = _Concatenator(
272         objs,
273         axis=axis,

~/pandas-dev/pandas/core/reshape/concat.py in __init__(self, objs, axis, join, keys, levels, names, ignore_index, verify_integrity, copy, sort)
449         self.copy = copy
450
--> 451         self.new_axes = self._get_new_axes()
452
453     def get_result(self):

~/pandas-dev/pandas/core/reshape/concat.py in _get_new_axes(self)
512     def _get_new_axes(self) -> List[Index]:
513         ndim = self._get_result_dim()
--> 514         return [
515             self._get_concat_axis() if i == self.bm_axis else self._get_comb_axis(i)
516             for i in range(ndim)

~/pandas-dev/pandas/core/reshape/concat.py in <listcomp>(.0)
513         ndim = self._get_result_dim()
514         return [
--> 515             self._get_concat_axis() if i == self.bm_axis else self._get_comb_axis(i)
516             for i in range(ndim)
517         ]

~/pandas-dev/pandas/core/reshape/concat.py in _get_concat_axis(self)
569             concat_axis = _concat_indexes(indexes)
570         else:
--> 571             concat_axis = _make_concat_multiindex(
572                 indexes, self.keys, self.levels, self.names
573             )

~/pandas-dev/pandas/core/reshape/concat.py in _make_concat_multiindex(indexes, keys, levels, names)
651             names = names + get_consensus_names(indexes)
652
--> 653         return MultiIndex(
654             levels=levels, codes=codes_list, names=names, verify_integrity=False
655         )

~/pandas-dev/pandas/core/indexes/multi.py in __new__(cls, levels, codes, sortorder, names, dtype, copy, name, verify_integrity, _set_identity)
281         # we've already validated levels and codes, so shortcut here
282         result._set_levels(levels, copy=copy, validate=False)
--> 283         result._set_codes(codes, copy=copy, validate=False)
284
285         result._names = [None] * len(levels)

~/pandas-dev/pandas/core/indexes/multi.py in _set_codes(self, codes, level, copy, validate, verify_integrity)
880
881         if level is None:
--> 882             new_codes = FrozenList(
883                 _coerce_indexer_frozen(level_codes, lev, copy=copy).view()
884                 for lev, level_codes in zip(self._levels, codes)

~/pandas-dev/pandas/core/indexes/multi.py in <genexpr>(.0)
881         if level is None:
882             new_codes = FrozenList(
--> 883                 _coerce_indexer_frozen(level_codes, lev, copy=copy).view()
884                 for lev, level_codes in zip(self._levels, codes)
885             )

~/pandas-dev/pandas/core/indexes/multi.py in _coerce_indexer_frozen(array_like, categories, copy)
3681         Non-writeable.
3682     """
-> 3683     array_like = coerce_indexer_dtype(array_like, categories)
3684     if copy:
3685         array_like = array_like.copy()

~/pandas-dev/pandas/core/dtypes/cast.py in coerce_indexer_dtype(indexer, categories)
866     length = len(categories)
867     if length < _int8_max:
--> 868         return ensure_int8(indexer)
869     elif length < _int16_max:
870         return ensure_int16(indexer)

~/pandas-dev/pandas/_libs/algos_common_helper.pxi in pandas._libs.algos.ensure_int8()
59             return arr
60         else:
---> 61             return arr.astype(np.int8, copy=copy)
62     else:
63         return np.array(arr, dtype=np.int8)

TypeError: int() argument must be a string, a bytes-like object or a number, not 'slice'

# Fixed code
def _make_concat_multiindex(indexes, keys, levels=None, names=None) -> MultiIndex:
    if (levels is None and isinstance(keys[0], tuple)) or (
        levels is not None and len(levels) > 1
    ):
        zipped = list(zip(*keys))
        if names is None:
            names = [None] * len(zipped)

        if levels is None:
            _, levels = factorize_from_iterables(zipped)
        else:
            levels = [ensure_index(x) for x in levels]
    else:
        zipped = [keys]
        if names is None:
            names = [None]

        if levels is None:
            levels = [ensure_index(keys)]
        else:
            levels = [ensure_index(x) for x in levels]

    if not all_indexes_same(indexes):
        codes_list = []

        # things are potentially different sizes, so compute the exact codes
        # for each level and pass those to MultiIndex.from_arrays

        for hlevel, level in zip(zipped, levels):
            to_concat = []
            for key, index in zip(hlevel, indexes):
                mask = level == key
                if not mask.any():
                    raise ValueError(f"Key {key} not in level {level}")
                i = np.nonzero(level == key)[0][0]

                to_concat.append(np.repeat(i, len(index)))
            codes_list.append(np.concatenate(to_concat))

        concat_index = _concat_indexes(indexes)

        # these go at the end
        if isinstance(concat_index, MultiIndex):
            levels.extend(concat_index.levels)
            codes_list.extend(concat_index.codes)
        else:
            codes, categories = factorize_from_iterable(concat_index)
            levels.append(categories)
            codes_list.append(codes)

        if len(names) == len(levels):
            names = list(names)
        else:
            # make sure that all of the passed indices have the same nlevels
            if not len({idx.nlevels for idx in indexes}) == 1:
                raise AssertionError(
                    "Cannot concat indices that do not have the same number of levels"
                )

            # also copies
            names = names + get_consensus_names(indexes)

        return MultiIndex(
            levels=levels, codes=codes_list, names=names, verify_integrity=False
        )

    new_index = indexes[0]
    n = len(new_index)
    kpieces = len(indexes)

    # also copies
    new_names = list(names)
    new_levels = list(levels)

    # construct codes
    new_codes = []

    # do something a bit more speedy

    for hlevel, level in zip(zipped, levels):
        hlevel = ensure_index(hlevel)
        mapped = level.get_indexer(hlevel)

        mask = mapped == -1
        if mask.any():
            raise ValueError(f"Values not found in passed level: {hlevel[mask]!s}")

        new_codes.append(np.repeat(mapped, n))

    if isinstance(new_index, MultiIndex):
        new_levels.extend(new_index.levels)
        new_codes.extend([np.tile(lab, kpieces) for lab in new_index.codes])
    else:
        new_levels.append(new_index)
        new_codes.append(np.tile(np.arange(n), kpieces))

    if len(new_names) < len(new_levels):
        new_names.extend(new_index.names)

    return MultiIndex(
        levels=new_levels, codes=new_codes, names=new_names, verify_integrity=False
    )