Skip to content

Figure.write_image() silently fails with invalid engine on Plotly 6.1.0 (macOS, Python 3.13), while plotly.io.write_image() errors correctly. #5188

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
junjiecai opened this issue May 18, 2025 · 0 comments

Comments

@junjiecai
Copy link

junjiecai commented May 18, 2025

(Environment):
Plotly Version: 6.1.0
Python Version: 3.13.2
Operating System: macOS (Seqonia 15.2)
Kaleido installed: No

When using Figure.write_image() method with an explicitly specified invalid engine name (e.g., a non-existent engine like "this_engine_does_not_exist"), the method does not raise the expected ValueError. Instead, it fails silently: no error is thrown, and no image file is produced.

However, when using the lower-level plotly.io.write_image(fig, ...) function with the same invalid engine, it correctly raises a ValueError: Invalid image export engine specified: ....

This discrepancy suggests an issue within the Figure.write_image() method's error handling or a difference in how it processes the engine parameter compared to the direct plotly.io.write_image() function, specifically on Plotly 6.1.0 under the described environment.

Code to reproduce

import plotly.graph_objects as go
import plotly.io as pio
from pathlib import Path
import os

print(f"--- System Info ---")
print(f"Plotly Version: {plotly.__version__}")
# Add Python version and OS version if easily accessible programmatically,
# otherwise, mention them manually in the "Environment" section.
# import sys
# print(f"Python Version: {sys.version}")
# import platform
# print(f"OS: {platform.system()} {platform.release()} ({platform.version()})")

# Create a simple figure
fig = go.Figure(data=[go.Scatter(x=[1, 2, 3], y=[4, 1, 2])])

output_dir = Path("./test_plotly_issue_output")
output_dir.mkdir(parents=True, exist_ok=True)
print(f"Output directory: {output_dir.resolve()}")

filename_fig_method = "test_fig_method"
filename_pio_func = "test_pio_func"
engine_to_test = "this_engine_definitely_does_not_exist"

# --- Test 1: Figure.write_image() method (EXPECTED TO FAIL SILENTLY in this scenario) ---
print(f"\\n--- Testing fig.write_image() with engine='{engine_to_test}' ---")
try:
    fig.write_image(
        str(output_dir / f"{filename_fig_method}.png"),
        engine=engine_to_test,
        width=600,
        height=400,
        scale=1
    )
    print(f"fig.write_image() did NOT raise an exception (UNEXPECTED for invalid engine).")
    # Check if file was created (it shouldn't be)
    if (output_dir / f"{filename_fig_method}.png").exists():
        print(f"File {filename_fig_method}.png was CREATED (UNEXPECTED for invalid engine).")
    else:
        print(f"File {filename_fig_method}.png was NOT created (as expected for failed export, but an error should have occurred).")
except ValueError as ve:
    print(f"fig.write_image() raised ValueError (EXPECTED, but not happening in the issue): {ve}")
except Exception as e:
    print(f"fig.write_image() raised an unexpected exception: {type(e).__name__}: {e}")
    import traceback
    traceback.print_exc()

# --- Test 2: plotly.io.write_image() function (EXPECTED TO RAISE ValueError) ---
print(f"\\n--- Testing pio.write_image() with engine='{engine_to_test}' ---")
try:
    pio.write_image(
        fig,
        str(output_dir / f"{filename_pio_func}.png"),
        engine=engine_to_test,
        width=600,
        height=400,
        scale=1
    )
    print(f"pio.write_image() did NOT raise an exception (UNEXPECTED for invalid engine).")
    if (output_dir / f"{filename_pio_func}.png").exists():
         print(f"File {filename_pio_func}.png was CREATED (UNEXPECTED for invalid engine).")
    else:
        print(f"File {filename_pio_func}.png was NOT created (as expected for failed export, but an error should have occurred).")
except ValueError as ve:
    print(f"pio.write_image() raised ValueError (EXPECTED and OBSERVED BEHAVIOR): {ve}")
except Exception as e:
    print(f"pio.write_image() raised an unexpected exception: {type(e).__name__}: {e}")
    import traceback
    traceback.print_exc()

print("\\n--- End of Test ---")```


Expected Behavior:
Both fig.write_image(engine="<invalid>") and plotly.io.write_image(fig, engine="<invalid>") should consistently raise a ValueError when an invalid engine name is specified.

Actual Behavior:
fig.write_image(engine="<invalid>") fails silently without raising an error and without producing an output file.
plotly.io.write_image(fig, engine="<invalid>") correctly raises a ValueError.


Additional Notes:
This issue was discovered while debugging why image export was failing silently in a larger project. The workaround was to replace calls to fig.write_image() with plotly.io.write_image().
The issue persists even if kaleido is uninstalled, suggesting it's not strictly about kaleido's presence but how Figure.write_image() handles the engine parameter lookup and subsequent errors.

Even with kaleido correctly installed, fig.write_image() will not work. No image file saved and just fail silently.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant