a-b-street/abstreet · critical

error building program

Error message

error building program: {:?}

What it means

During Prerender setup, the app compiles its embedded GLSL 300 shaders into a GPU program via glow. If program creation/linking fails, it panics with the glow error — the driver rejected the shaders, indicating an OpenGL/driver capability problem.

Solutions

  1. Update the graphics driver to one with solid OpenGL 3.x/GLSL 300 support
  2. Force up-to-date Mesa or vendor drivers (not legacy software renderers)
  3. Try LIBGL_ALWAYS_SOFTWARE=1 with a recent Mesa to rule out driver bugs
  4. Compare shader source (shaders/vertex_300.glsl, fragment_300.glsl) against the driver's supported GLSL version
Defensive patterns

Strategy: fallback

Validate before calling

// verify the context actually exposes GLSL 300 support before compiling
let ver = unsafe { gl.get_parameter_string(glow::SHADING_LANGUAGE_VERSION) };
eprintln!("GLSL version: {}", ver);

Try / catch

match Program::new(...) {
    Ok(p) => p,
    Err(e) => { eprintln!("shader link failed: {:?}; update drivers or use software rendering", e); std::process::exit(1); }
}

Prevention

When it happens

Trigger: Building the program from vertex_300.glsl/fragment_300.glsl fails because the created context doesn't actually support GLSL #version 300 es / OpenGL 3.x features used by the shaders.

Common situations: Software/old Mesa drivers with incomplete GLSL 300 support; buggy GPU drivers that fail to link valid shaders; running on hardware below the required OpenGL version after the context check passed loosely.

Related errors


AI-assisted analysis of a-b-street/abstreet@0964f29315 (2026-09-13). Data as JSON: /api/errors/cbf7951208d97086. Report an issue: GitHub.

Appendix: source

Thrown at widgetry/src/backend_glow_native.rs:54

    let program = unsafe {
        build_program(
            &gl,
            include_str!("../shaders/vertex_140.glsl"),
            include_str!("../shaders/fragment_140.glsl"),
        )
        .or_else(|err| {
            warn!(
                "unable to build program with default shaderrs, falling back to v300. error: {:?}",
                err
            );
            build_program(
                &gl,
                include_str!("../shaders/vertex_300.glsl"),
                include_str!("../shaders/fragment_300.glsl"),
            )
        })
        .unwrap_or_else(|err| {
            panic!("error building program: {:?}", err);
        })
    };

    (
        PrerenderInnards::new(gl, true, program, Some(WindowAdapter(windowed_context))),
        event_loop,
    )
}

pub struct WindowAdapter(glutin::WindowedContext<glutin::PossiblyCurrent>);

impl WindowAdapter {
    pub fn window(&self) -> &winit::window::Window {
        self.0.window()
    }

    pub fn window_resized(&self, new_size: ScreenDims, scale_factor: f64) {
        let physical_size = winit::dpi::LogicalSize::from(new_size).to_physical(scale_factor);

View on GitHub (pinned to 0964f29315)