niri-wm/niri · error
short texture mapping
Error message
short texture mapping
What it means
After copy_framebuffer renders into an intermediate texture and map_texture maps it into CPU memory, this check ensures the mapped byte slice is large enough to hold height rows of row_len bytes. A short mapping means the renderer returned fewer bytes than the declared buffer geometry expects, so copying to the shm pool would read out of bounds.
Source
Thrown at src/render_helpers/mod.rs:363
let _res = damage_tracker
.render_output_with_states(
renderer,
&mut target,
0,
elements,
Color32F::TRANSPARENT,
states,
)
.context("error rendering")?;
let mapping =
copy_framebuffer(renderer, &target, fourcc).context("error copying framebuffer")?;
let bytes = renderer
.map_texture(&mapping)
.context("error mapping texture")?;
ensure!(bytes.len() >= row_len * height, "short texture mapping");
unsafe {
let _span = tracy_client::span!("copy_nonoverlapping");
let dst = pool.add(offset);
if stride == row_len {
ptr::copy_nonoverlapping(bytes.as_ptr(), dst, row_len * height);
} else {
for y in 0..height {
ptr::copy_nonoverlapping(
bytes.as_ptr().add(y * row_len),
dst.add(y * stride),
row_len,
);
}
}
}
Ok(())View on GitHub (pinned to 9e72e4917c)
Solutions
- Check that the size passed to copy_framebuffer matches the output/framebuffer's actual dimensions at map time; recompute after any resize.
- Verify the fourcc format is supported by the renderer and that its bytes-per-pixel matches the mapping's actual layout (row_len vs mapping stride).
- Update the renderer/GPU driver; some backends return truncated mappings on texture copy failure.
- Guard the caller (render_for_screencopy_internal) to re-fetch output dimensions immediately before rendering to avoid size-change races.
Example fix
// before: trusting possibly stale size let size = output.current_size(); let mapping = copy_framebuffer(renderer, &target, fourcc)?; // after: validate mapped geometry against actual mapping let mapping = copy_framebuffer(renderer, &target, fourcc)?; assert_eq!(mapping.size, output.current_size(), "output resized mid-screencopy"); let bytes = renderer.map_texture(&mapping)?;
Defensive patterns
Strategy: validation
Validate before calling
// Validate mapping size before consuming it
let bytes = renderer.map_texture(&mapping)?;
let expected = row_len.checked_mul(height).expect("size overflow");
if bytes.len() < expected {
return Err(format!(
"mapped {} bytes, need {}",
bytes.len(), expected
));
} Type guard
fn is_full_mapping(bytes: &[u8], row_len: usize, height: usize) -> bool {
bytes.len() >= row_len.saturating_mul(height)
} Try / catch
match render_to_shm(...) {
Ok(()) => {},
Err(e) if e.to_string().contains("short texture mapping") => {
// re-fetch output size and retry once, or fall back to a different capture path
},
Err(e) => return Err(e),
} Prevention
- Re-read output/framebuffer dimensions immediately before rendering to avoid resize races.
- Confirm the renderer backend supports the requested fourcc and that its bpp matches row_len calculations.
- Keep the renderer and smithay/render_helpers versions in sync; stale backends can return truncated mappings.
- Log mapping dimensions on failure to distinguish driver truncation from geometry mismatches.
When it happens
Trigger: render_to_shm (via render_for_screencopy_internal) calls renderer.map_texture on the copy_framebuffer result and the returned slice length is < row_len * height — e.g. the renderer mapped only part of the texture, the framebuffer copy was clipped/smaller than the requested size, or the mapping's stride/format differs from what render_to_shm computed.
Common situations: Renderer backend (e.g. GL/gles vulkan) returning a mapping whose dimensions were clamped or failed partially; screencopy of an output whose logical size changed between size computation and mapping; format/fourcc mismatch causing row_len (width*bpp) to exceed the actual mapped buffer's stride*height; buggy or mismatched renderer versions.
Related errors
AI-assisted analysis of niri-wm/niri@9e72e4917c (2026-09-12).
Data as JSON: /api/errors/b7a9b31458683ba6.
Report an issue: GitHub.