a-b-street/abstreet · error · anyhow::Error
Can't take screenshots of dims
Error message
Can't take screenshots of dims {:?} when the window is only {:?} What it means
screenshot_everything captures the window contents at the requested ScreenDims; if the requested dimensions exceed the actual canvas window size, offscreen rendering would clip the screenshot, so the library refuses up front with this bail. It is a guard against producing cropped/invalid screenshots. The message echoes the requested dims and the actual window dims.
Solutions
- Start the app with a window at least as large as the requested screenshot dims (increase the window/canvas size)
- Lower the requested dims to fit within the current window dims
- If supported, use a prerendered/offscreen render path at higher resolution instead of window capture
- Check state.canvas.get_window_dims() first and clamp the requested dims
Example fix
// before screenshot_everything(dir, &prerender, zoom, ScreenDims::new(3840.0, 2160.0))?; // after let dims = ScreenDims::new(3840.0, 2160.0); let (w, h) = state.canvas.get_window_dims(); let dims = ScreenDims::new(dims.width.min(w), dims.height.min(h)); screenshot_everything(dir, &prerender, zoom, dims)?;
Defensive patterns
Strategy: validation
Validate before calling
let (win_w, win_h) = state.canvas.get_window_dims(); assert!(dims.width <= win_w && dims.height <= win_h, "screenshot dims exceed window");
Type guard
fn dims_fit(dims: &ScreenDims, canvas: &Canvas) -> bool {
dims.width <= canvas.window_width && dims.height <= canvas.window_height
} Try / catch
match screenshot_everything(dir, &prerender, zoom, dims) {
Ok(()) => (),
Err(e) => eprintln!("screenshot skipped: {e}"),
} Prevention
- Clamp requested dims to canvas.get_window_dims() before capturing
- Size the window to the desired screenshot resolution at startup
- Keep automated screenshot harness window sizes in sync with requested dims
- Prefer prerendered/offscreen capture for high-resolution output
When it happens
Trigger: Calling screenshot_everything (via run) with a dims argument whose width or height is greater than state.canvas.window_width / window_height — typically when the CLI-specified screenshot size exceeds the window size the app was started with.
Common situations: Passing --dims larger than the default window without raising the window size; running in a smaller monitor/virtual display; automated screenshot harness reusing a fixed window size with bigger desired output.
Understand the failure class
Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.
Related errors
- Can't delete ; it's not in the World
- Can't delete mid-drag
- Dropdown has default_value , but none of the choices match…
- Failed to load svg from bytes. cache_key
- to_geom called on a widget tree that has something…
AI-assisted analysis of a-b-street/abstreet@0964f29315 (2026-09-13).
Data as JSON: /api/errors/61aa1abf12194333.
Report an issue: GitHub.
Appendix: source
Thrown at widgetry/src/tools/screenshot.rs:15
use abstutil::Timer;
use crate::runner::State;
use crate::{Prerender, ScreenDims, SharedAppState};
/// Take a screenshot of the entire canvas, tiling it based on the window's width and height.
pub(crate) fn screenshot_everything<A: 'static + SharedAppState>(
state: &mut State<A>,
dir_path: &str,
prerender: &Prerender,
zoom: f64,
dims: ScreenDims,
) -> anyhow::Result<()> {
if dims.width > state.canvas.window_width || dims.height > state.canvas.window_height {
bail!(
"Can't take screenshots of dims {:?} when the window is only {:?}",
dims,
state.canvas.get_window_dims()
);
}
let mut timer = Timer::new("capturing screen");
let num_tiles_x = (state.canvas.map_dims.0 * zoom / dims.width).ceil() as usize;
let num_tiles_y = (state.canvas.map_dims.1 * zoom / dims.height).ceil() as usize;
let orig_zoom = state.canvas.cam_zoom;
let orig_x = state.canvas.cam_x;
let orig_y = state.canvas.cam_y;
timer.start_iter("capturing images", num_tiles_x * num_tiles_y);
state.canvas.cam_zoom = zoom;
fs_err::create_dir_all(dir_path)?;
// See https://github.com/a-b-street/abstreet/issues/671 for context. Some maps are so largeView on GitHub (pinned to 0964f29315)