emilk/egui · error
failed to construct C string from string for gl proc address
Error message
failed to construct C string from string for gl proc address
What it means
eframe builds a glow::Context from a loader closure; for every GL function name glow passes in, eframe converts it with std::ffi::CString::new, which fails if the string contains an interior NUL byte ('\0'). Real GL function names ('glGetString', 'glGenBuffers', ...) are plain ASCII literals and can never contain NUL, so this expect is effectively a defensive assert: firing it means the name supplied to the loader was corrupted or came from a mismatched/patched glow.
Source
Thrown at crates/eframe/src/native/glow_integration.rs:227
let mut glutin_window_context = unsafe {
GlutinWindowContext::new(egui_ctx, winit_window_builder, native_options, event_loop)?
};
// Creates the window - must come before we create our glow context
glutin_window_context.initialize_window(ViewportId::ROOT, event_loop)?;
{
let viewport = &glutin_window_context.viewports[&ViewportId::ROOT];
let window = viewport.window.as_ref().unwrap(); // Can't fail - we just called `initialize_all_viewports`
epi_integration::apply_window_settings(window, window_settings);
}
let gl = unsafe {
profiling::scope!("glow::Context::from_loader_function");
Arc::new(glow::Context::from_loader_function(|s| {
let s = std::ffi::CString::new(s)
.expect("failed to construct C string from string for gl proc address");
glutin_window_context.get_proc_address(&s)
}))
};
let painter = egui_glow::Painter::new(
gl,
"",
native_options.glow_options.shader_version,
native_options.dithering,
)?;
Ok((glutin_window_context, painter))
}
fn init_run_state(
&mut self,
event_loop: &ActiveEventLoop,View on GitHub (pinned to d802a982ce)
Solutions
- Report the panic upstream to egui with the full backtrace and glow/egui versions.
- Verify the glow and egui_glow versions come from the same release: cargo tree -p glow -p egui_glow.
- Audit any custom unsafe FFI code in your binary for memory corruption.
Defensive patterns
Strategy: try-catch
Try / catch
// Last-resort boundary for an eframe-internal panic:
let result = std::panic::catch_unwind(|| {
eframe::run_native("app", options, Box::new(|cc| Box::new(App::new(cc))))
});
if result.is_err() {
log::error!("renderer boot panicked; check glow/egui version skew");
} Prevention
- Keep egui, egui_glow and glow on the same release line (cargo tree -p glow -p egui_glow).
- Treat any hit of this expect as memory corruption or a fork bug and capture a backtrace (RUST_BACKTRACE=1).
- Avoid patching glow's loader naming; eframe relies on NUL-free literal names.
When it happens
Trigger: Calling run_native with the Glow renderer makes glow query many proc addresses through this closure. The panic only triggers if one of those names contains an embedded NUL byte, which stock glow never produces.
Common situations: Practically never observed. Theoretically reachable with version-skewed forks of glow/egui_glow that pass non-literal names, or with heap corruption caused by unrelated unsafe code in the process.
Related errors
- Single-use AppCreator has unexpectedly already been taken
- failed to fit multisamples option of native_options into u8
AI-assisted analysis of emilk/egui@d802a982ce (2026-08-16).
Data as JSON: /api/errors/c7266050ca52f3f3.
Report an issue: GitHub.