# Buggy code
def _fft(a, s, axes, norm, direction, value_type="C2C", overwrite_x=False, plan=None):
    if norm not in (None, "ortho"):
        raise ValueError('Invalid norm value %s, should be None or "ortho".' % norm)

    if s is not None:
        for n in s:
            if (n is not None) and (n < 1):
                raise ValueError(
                    "Invalid number of FFT data points (%d) specified." % n
                )

    if (s is not None) and (axes is not None) and len(s) != len(axes):
        raise ValueError("Shape and axes have different lengths.")

    if axes is None:
        if s is None:
            dim = a.ndim
        else:
            dim = len(s)
        axes = [i for i in range(-dim, 0)]
    else:
        axes = tuple(axes)
    if not axes:
        if value_type == "C2C":
            return a
        else:
            raise IndexError("list index out of range")
    a = _convert_dtype(a, value_type)
    a = _cook_shape(a, s, axes, value_type)

    if value_type == "C2C":
        a = _fft_c2c(a, direction, norm, axes, overwrite_x, plan=plan)
    elif value_type == "R2C":
        a = _exec_fft(a, direction, value_type, norm, axes[-1], overwrite_x)
        a = _fft_c2c(a, direction, norm, axes[:-1], overwrite_x)
    else:  # C2R
        a = _fft_c2c(a, direction, norm, axes[:-1], overwrite_x)
        # _cook_shape tells us input shape only, and no output shape
        out_size = _get_fftn_out_size(a.shape, s, axes[-1], value_type)
        a = _exec_fft(a, direction, value_type, norm, axes[-1], overwrite_x, out_size)

    return a


# Traceback (ValueError)
np.fft.fft(np.array([]))
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<__array_function__ internals>", line 5, in fft
File "/path/to/python3.8/site-packages/numpy-1.18.2-py3.8-linux-x86_64.egg/numpy/fft/_pocketfft.py", line 188, in fft
output = _raw_fft(a, n, axis, False, True, inv_norm)
File "/path/to/python3.8/site-packages/numpy-1.18.2-py3.8-linux-x86_64.egg/numpy/fft/_pocketfft.py", line 57, in _raw_fft
raise ValueError("Invalid number of FFT data points (%d) specified."
ValueError: Invalid number of FFT data points (0) specified.
cupy.fft.fft(cupy.array([]))
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/path/to/cupy/cupy/fft/fft.py", line 496, in fft
return _fft(a, (n,), (axis,), norm, cupy.cuda.cufft.CUFFT_FORWARD)
File "/path/to/cupy/cupy/fft/fft.py", line 175, in _fft
a = _fft_c2c(a, direction, norm, axes, overwrite_x, plan=plan)
File "/path/to/cupy/cupy/fft/fft.py", line 142, in _fft_c2c
a = _exec_fft(a, direction, 'C2C', norm, axis, overwrite_x, plan=plan)
File "/path/to/cupy/cupy/fft/fft.py", line 91, in _exec_fft
batch = a.size // a.shape[-1]
ZeroDivisionError: integer division or modulo by zero
cupy.fft.fft(cupy.array([]), n=0)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/path/to/cupy/cupy/fft/fft.py", line 496, in fft
return _fft(a, (n,), (axis,), norm, cupy.cuda.cufft.CUFFT_FORWARD)
File "/path/to/cupy/cupy/fft/fft.py", line 155, in _fft
raise ValueError(
ValueError: Invalid number of FFT data points (0) specified.

# Fixed code
def _fft(a, s, axes, norm, direction, value_type="C2C", overwrite_x=False, plan=None):
    if norm not in (None, "ortho"):
        raise ValueError('Invalid norm value %s, should be None or "ortho".' % norm)

    if (s is not None) and (axes is not None) and len(s) != len(axes):
        raise ValueError("Shape and axes have different lengths.")

    if axes is None:
        if s is None:
            dim = a.ndim
        else:
            dim = len(s)
        axes = [i for i in range(-dim, 0)]
    else:
        axes = tuple(axes)
    if not axes:
        if value_type == "C2C":
            return a
        else:
            raise IndexError("list index out of range")
    a = _convert_dtype(a, value_type)
    a = _cook_shape(a, s, axes, value_type)

    if value_type == "C2C":
        a = _fft_c2c(a, direction, norm, axes, overwrite_x, plan=plan)
    elif value_type == "R2C":
        a = _exec_fft(a, direction, value_type, norm, axes[-1], overwrite_x)
        a = _fft_c2c(a, direction, norm, axes[:-1], overwrite_x)
    else:  # C2R
        a = _fft_c2c(a, direction, norm, axes[:-1], overwrite_x)
        # _cook_shape tells us input shape only, and no output shape
        out_size = _get_fftn_out_size(a.shape, s, axes[-1], value_type)
        a = _exec_fft(a, direction, value_type, norm, axes[-1], overwrite_x, out_size)

    return a