fyne-io/fyne · critical
XGetVisualInfo failed\n
Error message
XGetVisualInfo failed\n
What it means
x11.c takes the EGL native visual id and calls XGetVisualInfo with VisualIDMask to obtain the X visual for window creation. If the X server has no visual with that id, the call returns NULL and the process prints 'XGetVisualInfo failed' and exits(1). The EGL and X stacks disagree about which visual to use.
Source
Thrown at internal/driver/mobile/app/x11.c:47
};
EGLConfig config;
EGLint num_configs;
if (!eglChooseConfig(e_dpy, attribs, &config, 1, &num_configs)) {
fprintf(stderr, "eglChooseConfig failed\n");
exit(1);
}
EGLint vid;
if (!eglGetConfigAttrib(e_dpy, config, EGL_NATIVE_VISUAL_ID, &vid)) {
fprintf(stderr, "eglGetConfigAttrib failed\n");
exit(1);
}
XVisualInfo visTemplate;
visTemplate.visualid = vid;
int num_visuals;
XVisualInfo *visInfo = XGetVisualInfo(x_dpy, VisualIDMask, &visTemplate, &num_visuals);
if (!visInfo) {
fprintf(stderr, "XGetVisualInfo failed\n");
exit(1);
}
Window root = RootWindow(x_dpy, DefaultScreen(x_dpy));
XSetWindowAttributes attr;
attr.colormap = XCreateColormap(x_dpy, root, visInfo->visual, AllocNone);
if (!attr.colormap) {
fprintf(stderr, "XCreateColormap failed\n");
exit(1);
}
attr.event_mask = StructureNotifyMask | ExposureMask |
ButtonPressMask | ButtonReleaseMask | ButtonMotionMask;
Window win = XCreateWindow(
x_dpy, root, 0, 0, w, h, 0, visInfo->depth, InputOutput,
visInfo->visual, CWColormap | CWEventMask, &attr);
XFree(visInfo);View on GitHub (pinned to 8860ee95c3)
Solutions
- Run on an X server with standard 24-bit TrueColor visuals (check xdpyinfo | grep -A5 visuals)
- Start virtual X with adequate visuals: xvfb-run -a -s '-screen 0 1024x768x24' ./yourapp
- Force software Mesa so EGL picks visuals the server actually has: LIBGL_ALWAYS_SOFTWARE=1 ./yourapp
- Update Mesa/vendor driver to fix EGL/X visual mismatches
- Patch x11.c to fall back to the default visual when XGetVisualInfo finds nothing
Example fix
// before (x11.c): exit when no X visual matches the EGL visual id
XVisualInfo *visInfo = XGetVisualInfo(x_dpy, VisualIDMask, &visTemplate, &num_visuals);
if (!visInfo) { fprintf(stderr, "XGetVisualInfo failed\n"); exit(1); }
// after: retry with the screen's default visual
XVisualInfo *visInfo = XGetVisualInfo(x_dpy, VisualIDMask, &visTemplate, &num_visuals);
if (!visInfo) {
visTemplate.visualid = XVisualIDFromVisual(DefaultVisual(x_dpy, DefaultScreen(x_dpy)));
visInfo = XGetVisualInfo(x_dpy, VisualIDMask, &visTemplate, &num_visuals);
if (!visInfo) { exit(1); }
} Defensive patterns
Strategy: validation
Validate before calling
func visualPreflight() error {
out, err := exec.Command("sh", "-c", "xdpyinfo | grep -c 'TrueColor'").Output()
if err != nil || strings.TrimSpace(string(out)) == "0" {
return fmt.Errorf("X server has no TrueColor visuals; use 24-bit depth (xvfb -screen 0 1024x768x24)")
}
return nil
} Prevention
- Always run virtual X servers at 24-bit depth so TrueColor visuals exist
- Prefer local displays over remote/forwarded ones for GPU apps
- Check xdpyinfo visuals when setting up new display environments
When it happens
Trigger: EGL reports a native visual id that does not exist on the connected X server: Xvfb with a limited set of visuals, remote X displays, mismatched vendor EGL vs the server's visuals, or unusual depths (16-bit displays).
Common situations: Running under plain Xvfb or VNC without full 24-bit TrueColor; NVIDIA proprietary EGL over a remote/ssh-forwarded display; multi-monitor X servers with per-screen visuals.
Related errors
- eglChooseConfig failed\n
- XCreateColormap failed\n
- eglGetConfigAttrib failed\n
- eglCreateWindowSurface failed\n
- XOpenDisplay failed\n
AI-assisted analysis of fyne-io/fyne@8860ee95c3 (2026-08-15).
Data as JSON: /api/errors/2caff0b2d7668e4f.
Report an issue: GitHub.