def METHOD_NAME(self, exception_index):
    # note that we insert in reversed order
    lines = []
    last_sp = 0
    start_backtrace_index = self.exception_info[exception_index][1]
    zipped = list(zip(self.traceback[start_backtrace_index:],
                      self.stack_pointers[start_backtrace_index:]))
    exception = self.exceptions[exception_index]
    name = exception[0]
    message = exception[1]
    params = exception[2]
    if ':' in name:
        exn_id, name = name.split(':', 2)
        exn_id = int(exn_id)
    else:
        exn_id = 0
    lines.append("{}({}): {}".format(name, exn_id, message.format(*params)))
    zipped.append(((exception[3], exception[4], exception[5], exception[6],
                   None, []), None))
    for ((filename, line, column, function, address, inlined), sp) in zipped:
        # backtrace of nested exceptions may be discontinuous
        # but the stack pointer must increase monotonically
        if sp is not None and sp <= last_sp:
            continue
        last_sp = sp
        for record in reversed(inlined):
            lines += self.append_backtrace(record, True)
        lines += self.append_backtrace((filename, line, column, function,
                                        address))
    lines.append("Traceback (most recent call first):")
    return "\n".join(reversed(lines))