Why blender throws an exception when saving a copy of image?
You can use save_render() to save to whatever format you want, no need to duplicate an image datablock first.

In my experience, save_render() is the only reliable way to export from one format to another. I tried the .filepath_raw / .file_format way as well, but it turned out to not actually write the data in the expected format (it used the source format with target format's extension).

Note that save_render() does not render anything, it is called ..._render because it uses the render settings of the current scene.

import bpy

img = bpy.data.images[0] # pick an image datablock
filepath = r"C:\tmp\_exported_image.tif" # specify outout filepath here

# Store current render settings
settings = bpy.context.scene.render.image_settings
format = settings.file_format
mode = settings.color_mode
depth = settings.color_depth

# Change render settings to our target format
settings.file_format = 'TIFF'
settings.color_mode = 'RGBA'
settings.color_depth = '8'

# Save image to TIF, this does NOT render anything!
# It only means that the save command will use the current scene's render settings.
img.save_render(filepath)

# Restore previous render settings
settings.file_format = format
settings.color_mode = mode
settings.color_depth = depth