kitao/pyxel · critical

pyxel.flip is not supported on Pyxel Web

Error message

pyxel.flip is not supported on Pyxel Web

What it means

Pyxel's SDL2 platform intentionally replaces `flip` with a panicking stub when compiled for emscripten (Pyxel Web). Web builds render frames through the browser event loop instead of an explicit SDL surface flip, so calling `pyxel.flip` there is unsupported and aborts the program.

Source

Thrown at crates/pyxel-core/src/platform/sdl2/platform_sdl2.rs:544

            if remaining_ms <= 0.0 {
                break;
            }
            unsafe { SDL_Delay((remaining_ms as u32 / 2).max(1)) };
        }

        self.swap_window();

        // Catch up if frames were missed
        let ticks = self.ticks() as f32;
        while next_frame_ms <= ticks {
            next_frame_ms += frame_ms;
        }
        self.next_update_ms = Some(next_frame_ms);
    }

    #[cfg(target_os = "emscripten")]
    pub fn step_frame(&mut self, _fps: u32) {
        panic!("pyxel.flip is not supported on Pyxel Web");
    }

    // OpenGL

    pub fn gl_profile(&self) -> GlProfile {
        let mut value = 0i32;
        unsafe { SDL_GL_GetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, &raw mut value) };

        if value & SDL_GL_CONTEXT_PROFILE_CORE as i32 != 0 {
            GlProfile::Gl
        } else if value & SDL_GL_CONTEXT_PROFILE_ES as i32 != 0 {
            GlProfile::Gles
        } else {
            GlProfile::None
        }
    }

    #[cfg(not(target_os = "emscripten"))]

View on GitHub (pinned to 50f9bd7778)

Solutions

  1. Remove the `pyxel.flip()` call or wrap it in `#[cfg(not(target_os = "emscripten"))]` so it only runs on native builds.
  2. Rely on Pyxel's Web run loop to present frames instead of manual flipping.
  3. If a manual present is needed, use the platform-appropriate API behind a cfg attribute.

Example fix

// before
pyxel.flip();
// after
#[cfg(not(target_os = "emscripten"))]
pyxel.flip();
Defensive patterns

Strategy: try-catch

Validate before calling

// guard before calling
if cfg!(target_os = "emscripten") {
    // web: rendering is handled by the run loop; do not flip
} else {
    pyxel.flip();
}

Type guard

fn flip_supported() -> bool {
    !cfg!(target_os = "emscripten")
}

Try / catch

// panic in Rust cannot be caught portably here; prevent it instead
if flip_supported() { pyxel.flip(); }

Prevention

When it happens

Trigger: Calling `pyxel.flip()` in code compiled to WebAssembly (cargo build --target wasm32-unknown-emscripten / Pyxel Web runner). The panic fires in the platform's step_frame on the emscripten cfg path.

Common situations: Cross-platform code that flips manually on desktop builds but also gets compiled for the Web without cfg-gating; tutorials or samples that use flip unconditionally; porting an existing desktop Pyxel app to Pyxel Web.

Related errors


AI-assisted analysis of kitao/pyxel@50f9bd7778 (2026-09-03). Data as JSON: /api/errors/9e514260f1e0ef81. Report an issue: GitHub.