Troubleshooting
Symptoms, causes, and direct fixes for identity, rendering, repaint, and input failures.
Duplicate widget/paint ID
Reported as an IdCollision in Context::diagnostics() (and framed by the debug
overlay). Two same-kind controls have the same caption and scope, or two windows share an ID.
Add unique ##suffix strings, id_source, or a stable Ui::push_id scope. For
changing captions, use explicit identity. See IDs.
Window position resets after changing its title
The title forms the default window ID. Set .id(Id::new("stable-panel-key")) before
show. Changing default_position does not force an existing window to move;
it supplies only initial geometry. See Window.
UI does not update after a worker changes state
Request native window.request_redraw() after publishing the new model value.
context.request_repaint() alone does not wake a custom host. For workers that
survive native-window recreation, refresh the redraw handle or use a host user event.
See Repaint scheduling.
Earlier controls show the previous value
Mutating after a control has already been built affects the next pass. Standard
Ui::add helpers request this follow-up on click/value change. For custom model
mutations unrelated to a widget response, call request_repaint. Custom hosts must
honor needs_repaint() after the pass.
High CPU usage while idle
Remove unconditional redraws and ControlFlow::Poll. Check whether set_style or
request_repaint is called every UI pass. Use Wait when idle and WaitUntil for
future deadlines. Delay RenderStatus::Retry attempts. See Performance.
Fast clicks are missed
Forward each event to Context::on_window_event as it arrives. Do not reduce input
to the final held state or rebuild the context each frame. Hit regions come from the
last completed UI pass; a control must have been built before it can receive input.
See Input.
Content disappears at the panel bottom
The content is clipped; there is no automatic scrolling. Increase panel height or split content into application-controlled sections. Resizable windows reserve space near the grip. See Layout.
Slider changes without pointer input
Enabled sliders normalize their values each pass. Set valid values and a suitable step, or disable the control to preserve an unnormalized value. Steps are relative to the range minimum. See Slider.
Pointer positions do not match drawing at high DPI
Pass native physical size and actual scale factor to set_viewport. Keep UI
coordinates logical; the event bridge divides physical pointer positions by scale.
Refresh from window.inner_size() and window.scale_factor() after resize/DPI events.
Do not multiply widget dimensions by DPI yourself.
Invalid UI draw data
Read the specific RenderError::InvalidDrawData message:
| Message concerns | Fix |
|---|---|
| Viewport and scale | Supply finite positive logical size and scale |
| Mesh indices | Use global indices below the vertex count |
| Nonfinite vertices | Remove NaN/infinite position, UV, or color fields |
| Draw range / clip / texture | Use valid index-vector ranges, finite clips, and supplied texture IDs |
| Texture size / RGBA count | Nonzero supported dimensions; exactly width × height × 4 bytes |
| GPU buffer / texture limits | Reduce the frame, payload, or physical surface size |
For custom producers, increment revision after changing geometry or commands and
increment each image revision after changing its pixels. See Drawing protocol.
GPU initialization or surface failure
Capture the full RunError/RenderError. For a custom host, log adapter_info()
after successful initialization. A native display and compatible GPU backend are
required; GPU smoke tests cannot be replaced by a headless HTML preview.
Handle Retry with backoff and Dormant by waiting for relevant events. Recreate
the renderer on DeviceLost; lost/outdated surfaces are recovered inside render.
See Renderer.
The page stays blank or fails to start (browser)
Open the console: the runner writes startup errors, panics with their message, and the
chosen backend (zaxis: BrowserWebGpu renderer on ...) there.
| Symptom | Cause and fix |
|---|---|
RunError::Web / "there is no element with id" | canvas_id or container_id names an element the page does not have yet. Run after the element exists, for example from a type="module" script |
| "finding a GPU adapter" | Neither WebGPU nor WebGL2 is available (hardware acceleration off, blocklisted GPU). Try ?zaxis_backend=webgl2 or enable acceleration |
| Works with WebGL2 only | WebGPU is missing or disabled in that browser; no action needed, or force it with ?zaxis_backend=webgpu to see the error |
| Wasm fails to load / wrong MIME type | Serve .wasm as application/wasm over HTTP(S), not file:// |
wasm-bindgen schema mismatch | The CLI must match wasm-bindgen in Cargo.lock (cargo install wasm-bindgen-cli --version <it>) |
time not implemented on this platform | Code outside zaxis calls std::time::Instant::now(); use zaxis::Instant |
| Text missing or boxes | No system fonts in a page: enable the bundled-* features or load a FontFamily |
| Image never appears | ImageSource::path cannot work in a page; use bytes, encoded or rgba |
| Paste does nothing | Needs a real Ctrl/Cmd+V in the canvas: the text comes from the paste event. Custom hosts need Context::set_clipboard |
| Copy reports "clipboard unavailable" | navigator.clipboard needs HTTPS or localhost and a recent gesture; the copy event path still works from the key press |
| Canvas blurry on a high-density screen | Give the canvas CSS size, not a fixed width/height attribute; winit sets the backing store |
| Frozen after a GPU or driver reset | WebGPU device loss recovers by itself; a lost WebGL context needs a page reload |
Missing glyphs or incorrect script layout
The engine supports complex shaping and bidirectional layout. Bundled Noto Color Emoji
provides emoji; other script coverage depends on installed fallback fonts. Install a
font covering the script, restart the application so the shared font database is
rebuilt, or pass a primary family with RunOptions::with_font_family (or
Context::with_fonts in a custom host).
See Text and fonts.
Files dragged from Explorer are refused
Windows blocks drag and drop from a lower integrity level into a higher one (UIPI): if the
application runs as administrator and Explorer does not, the cursor shows "not allowed" and no
event arrives. Run both at the same level. On Wayland the position of a drag is not reported, so a
drop reaches a target only when it is the single one that accepts the files; a missing
xdg-desktop-portal makes file dialogs return Cancelled.