# Buggy code
def convert(
    ctx,
    files,
    output,
    driver,
    dtype,
    scale_ratio,
    scale_offset,
    photometric,
    overwrite,
    creation_options,
):
    """Copy and convert raster datasets to other data types and formats.

    Data values may be linearly scaled when copying by using the
    --scale-ratio and --scale-offset options. Destination raster values
    are calculated as

      dst = scale_ratio * src + scale_offset

    For example, to scale uint16 data with an actual range of 0-4095 to
    0-255 as uint8:

      $ rio convert in16.tif out8.tif --dtype uint8 --scale-ratio 0.0625

    Format specific creation options may also be passed using --co. To
    tile a new GeoTIFF output file, do the following.

      --co tiled=true --co blockxsize=256 --co blockysize=256

    To compress it using the LZW method, add

      --co compress=LZW

    """
    with ctx.obj["env"]:
        outputfile, files = resolve_inout(
            files=files, output=output, overwrite=overwrite
        )
        inputfile = files[0]

        with rasterio.open(inputfile) as src:
            # Use the input file's profile, updated by CLI
            # options, as the profile for the output file.
            profile = src.profile

            if driver:
                profile["driver"] = driver

            if dtype:
                profile["dtype"] = dtype
            dst_dtype = profile["dtype"]

            if photometric:
                creation_options["photometric"] = photometric

            profile.update(**creation_options)

            with rasterio.open(outputfile, "w", **profile) as dst:
                data = src.read()

                if scale_ratio:
                    # Cast to float64 before multiplying.
                    data = data.astype("float64", casting="unsafe", copy=False)
                    np.multiply(data, scale_ratio, out=data, casting="unsafe")

                if scale_offset:
                    # My understanding of copy=False is that this is a
                    # no-op if the array was cast for multiplication.
                    data = data.astype("float64", casting="unsafe", copy=False)
                    np.add(data, scale_offset, out=data, casting="unsafe")

                # Cast to the output dtype and write.
                result = data.astype(dst_dtype, casting="unsafe", copy=False)
                dst.write(result)


# Traceback (IndexError)
$ rio convert --overwrite 20200829.tif
Traceback (most recent call last):
File "/usr/local/bin/rio", line 8, in <module>
sys.exit(main_group())
File "/usr/local/lib/python3.8/dist-packages/click/core.py", line 829, in __call__
return self.main(*args, **kwargs)
File "/usr/local/lib/python3.8/dist-packages/click/core.py", line 782, in main
rv = self.invoke(ctx)
File "/usr/local/lib/python3.8/dist-packages/click/core.py", line 1259, in invoke
return _process_result(sub_ctx.command.invoke(sub_ctx))
File "/usr/local/lib/python3.8/dist-packages/click/core.py", line 1066, in invoke
return ctx.invoke(self.callback, **ctx.params)
File "/usr/local/lib/python3.8/dist-packages/click/core.py", line 610, in invoke
return callback(*args, **kwargs)
File "/usr/local/lib/python3.8/dist-packages/click/decorators.py", line 21, in new_func
return f(get_current_context(), *args, **kwargs)
File "/usr/local/lib/python3.8/dist-packages/rasterio/rio/convert.py", line 55, in convert
inputfile = files[0]
IndexError: list index out of range

# Fixed code
def convert(
    ctx,
    files,
    output,
    driver,
    dtype,
    scale_ratio,
    scale_offset,
    photometric,
    overwrite,
    creation_options,
):
    """Copy and convert raster datasets to other data types and formats.

    Data values may be linearly scaled when copying by using the
    --scale-ratio and --scale-offset options. Destination raster values
    are calculated as

      dst = scale_ratio * src + scale_offset

    For example, to scale uint16 data with an actual range of 0-4095 to
    0-255 as uint8:

      $ rio convert in16.tif out8.tif --dtype uint8 --scale-ratio 0.0625

    Format specific creation options may also be passed using --co. To
    tile a new GeoTIFF output file, do the following.

      --co tiled=true --co blockxsize=256 --co blockysize=256

    To compress it using the LZW method, add

      --co compress=LZW

    """
    with ctx.obj["env"]:
        outputfile, files = resolve_inout(
            files=files, output=output, overwrite=overwrite, num_inputs=1
        )
        inputfile = files[0]

        with rasterio.open(inputfile) as src:
            # Use the input file's profile, updated by CLI
            # options, as the profile for the output file.
            profile = src.profile

            if driver:
                profile["driver"] = driver

            if dtype:
                profile["dtype"] = dtype
            dst_dtype = profile["dtype"]

            if photometric:
                creation_options["photometric"] = photometric

            profile.update(**creation_options)

            with rasterio.open(outputfile, "w", **profile) as dst:
                data = src.read()

                if scale_ratio:
                    # Cast to float64 before multiplying.
                    data = data.astype("float64", casting="unsafe", copy=False)
                    np.multiply(data, scale_ratio, out=data, casting="unsafe")

                if scale_offset:
                    # My understanding of copy=False is that this is a
                    # no-op if the array was cast for multiplication.
                    data = data.astype("float64", casting="unsafe", copy=False)
                    np.add(data, scale_offset, out=data, casting="unsafe")

                # Cast to the output dtype and write.
                result = data.astype(dst_dtype, casting="unsafe", copy=False)
                dst.write(result)