linebender/druid · error

no present opcode

Error message

no present opcode

What it means

Error in initialize_present_data: the X server does not support the Present extension (no present opcode), so present-based frame timing (PRESENT Complete/Idle notify) cannot be initialized. It fires during window build on X servers without the Present extension; callers (build) treat this as a non-fatal signal to skip present data.

Solutions

  1. Fall back to a non-Present timing path (e.g. timer-driven animation) when the opcode is missing
  2. Query the Present extension version and degrade gracefully if unsupported
  3. Gate animation timing code on the presence of Present support
Defensive patterns

Strategy: fallback

When it happens

Trigger: Thrown at druid-shell/src/backend/x11/window.rs:529 when the library encounters an invalid state.

Common situations: See trigger scenarios.


AI-assisted analysis of linebender/druid@0f8b1195e4 (2026-09-10). Data as JSON: /api/errors/e6f5475a338f4fe3. Report an issue: GitHub.

Appendix: source

Thrown at druid-shell/src/backend/x11/window.rs:529

                EventMask::COMPLETE_NOTIFY | EventMask::IDLE_NOTIFY,
            )?
            .check()
            .context("set present event mask")?;

            let region_id = conn.generate_id()?;
            conn.xfixes_create_region(region_id, &[])
                .context("create region")?;

            Ok(PresentData {
                serial: 0,
                region: region_id,
                waiting_on: None,
                needs_present: false,
                last_msc: None,
                last_ust: None,
            })
        } else {
            Err(anyhow!("no present opcode"))
        }
    }
}

/// An X11 window.
//
// We use lots of RefCells here, so to avoid panics we need some rules. The basic observation is
// that there are two ways we can end up calling the code in this file:
//
// 1) it either comes from the system (e.g. through some X11 event), or
// 2) from the client (e.g. druid, calling a method on its `WindowHandle`).
//
// Note that 2 only ever happens as a result of 1 (i.e., the system calls us, we call the client
// using the `WinHandler`, and it calls us back). The rules are:
//
// a) We never call into the system as a result of 2. As a consequence, we never get 1
//    re-entrantly.
// b) We *almost* never call into the `WinHandler` while holding any of the other RefCells. There's

View on GitHub (pinned to 0f8b1195e4)