Skip to content
Latchkey

matplotlib "no display name and no $DISPLAY" - Use the Agg Backend in CI

matplotlib defaulted to an interactive GUI backend that needs an X display, but CI runners are headless. The fix is to use the non-interactive Agg backend, which renders straight to image files without a display.

What this error means

Importing pyplot or calling plt.show()/a GUI backend in CI fails with no display name and no $DISPLAY environment variable or a TclError. The same plotting code works locally where a window system is present.

Python traceback
tkinter.TclError: no display name and no $DISPLAY environment variable
# or
RuntimeError: Invalid DISPLAY variable
  File ".../matplotlib/backends/backend_tkagg.py", ...

Common causes

Interactive backend on a headless runner

matplotlib selected a GUI backend (TkAgg/Qt) that requires an X server. CI has no display, so backend initialization fails.

Calling plt.show() in CI

Even with a file-based backend, plt.show() tries to open a window. In headless CI you should save figures, not show them.

How to fix it

Force the Agg backend

Select Agg before importing pyplot - via env var (cleanest for CI) or matplotlib.use.

Terminal / Python
export MPLBACKEND=Agg
# or in code, before importing pyplot:
# import matplotlib; matplotlib.use("Agg")

Save figures instead of showing them

Python
import matplotlib
matplotlib.use("Agg")
import matplotlib.pyplot as plt
plt.plot([1, 2, 3])
plt.savefig("out.png")   # no plt.show()

How to prevent it

  • Set MPLBACKEND=Agg in CI for all plotting jobs.
  • Save figures to files; never call plt.show() in CI.
  • Avoid GUI backends and the Tk dependency in headless environments.

Related guides

Tired of flaky CI? Latchkey auto-heals failed jobs and retries them for you. Start free →