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

  1. Check that the size passed to copy_framebuffer matches the output/framebuffer's actual dimensions at map time; recompute after any resize.
  2. 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).
  3. Update the renderer/GPU driver; some backends return truncated mappings on texture copy failure.
  4. 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

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.