gfx-rs/wgpu · error

Couldn't acquire program_cache lock

Error message

Couldn't acquire program_cache lock

What it means

Panic in the GLES device during pipeline creation: the shared program_cache mutex could not be locked, which for this mutex signals a poisoned/deadlocked state (another thread panicked while holding it). The faulty input is the lock state of the shared cache.

Solutions

  1. Avoid concurrent pipeline creation races that poison the lock
  2. Restart the process; investigate the earlier panic that poisoned the mutex
Defensive patterns

Strategy: retry

When it happens

Trigger: Thrown at wgpu-hal/src/gles/device.rs:495 when the library encounters an invalid state.

Common situations: See trigger scenarios.


AI-assisted analysis of gfx-rs/wgpu@3e11ff59bf (2026-09-03). Data as JSON: /api/errors/072370db87f4f7b7. Report an issue: GitHub.

Appendix: source

Thrown at wgpu-hal/src/gles/device.rs:495

        let group_to_binding_to_slot = layout
            .group_infos
            .iter()
            .map(|group| group.as_ref().map(|group| group.binding_to_slot.clone()))
            .collect::<Vec<_>>();
        for &(naga_stage, stage) in &shaders {
            program_stages.push(super::ProgramStage {
                naga_stage: naga_stage.to_owned(),
                shader_id: stage.module.id,
                entry_point: stage.entry_point.to_owned(),
                zero_initialize_workgroup_memory: stage.zero_initialize_workgroup_memory,
                constant_hash: Self::create_constant_hash(stage),
            });
        }
        let mut guard = self
            .shared
            .program_cache
            .try_lock()
            .expect("Couldn't acquire program_cache lock");
        // This guard ensures that we can't accidentally destroy a program whilst we're about to reuse it
        // The only place that destroys a pipeline is also locking on `program_cache`
        let program = guard
            .entry(super::ProgramCacheKey {
                stages: program_stages,
                group_to_binding_to_slot: group_to_binding_to_slot.into_boxed_slice(),
            })
            .or_insert_with(|| unsafe {
                Self::create_program(
                    gl,
                    shaders,
                    layout,
                    label,
                    multiview_mask,
                    self.shared.shading_language_version,
                    self.shared.private_caps,
                )
            })

View on GitHub (pinned to 3e11ff59bf)