GraphiteEditor/Graphite · critical

Buffer mapping communication failed

Error message

Buffer mapping communication failed

What it means

When converting a list of GPU rasters to CPU (texture_conversion.rs:191), the executor submits one batched copy encoder and then awaits map futures for every readback buffer. Each converter polls the device (wgt::PollType::wait_indefinitely) and resolves a channel with the map_async result; try_join_all fails if any single buffer map is rejected (device lost, buffer invalid, mapping error), and .expect("Buffer mapping communication failed") aborts the whole batch conversion. The map error originates in wgpu's map_async callback being invoked with an error.

Source

Thrown at node-graph/libraries/wgpu-executor/src/texture_conversion.rs:219

		let mut rows_meta = Vec::new();

		for row in self {
			let (element, attributes) = row.into_parts();
			converters.push(RasterGpuToRasterCpuConverter::new(device, &mut encoder, element));
			rows_meta.push(Item::from_parts((), attributes));
		}

		queue.submit([encoder.finish()]);

		let mut map_futures = Vec::new();
		for converter in converters {
			map_futures.push(converter.convert(device));
		}

		let map_results = futures::future::try_join_all(map_futures)
			.await
			.map_err(|_| "Failed to receive map result")
			.expect("Buffer mapping communication failed");

		map_results
			.into_iter()
			.zip(rows_meta)
			.map(|(element, row)| {
				let (_, attributes) = row.into_parts();
				Item::from_parts(element, attributes)
			})
			.collect()
	}
}

/// Converts single GPU raster to CPU by downloading texture data
impl<'i> Convert<Raster<CPU>, &'i WgpuExecutor> for Raster<GPU> {
	async fn convert(self, _: Footprint, executor: &'i WgpuExecutor) -> Raster<CPU> {
		let device = &executor.context().device;
		let queue = &executor.context().queue;

View on GitHub (pinned to c507b35645)

Solutions

  1. Check for device loss first: register a device-lost / uncaptured-error handler on the wgpu device; if lost, re-create the WgpuExecutor and retry the conversion once
  2. Verify readback buffers are created with MAP_READ | COPY_DST usage and outlive their pending maps (do not drop converters or their buffers early)
  3. Propagate the failure instead of .expect: return a conversion error from the trait method so callers can retry or degrade per-image
  4. If it only fails for very large batches, split the list into smaller batches to limit blast radius and identify the offending raster

Example fix

// before
let map_results = futures::future::try_join_all(map_futures)
    .await
    .map_err(|_| "Failed to receive map result")
    .expect("Buffer mapping communication failed");

// after
let map_results = futures::future::try_join_all(map_futures)
    .await
    .map_err(|_| RasterConversionError::BufferMapFailed)?; // caller re-creates the executor on device loss, then retries
Defensive patterns

Strategy: retry

Validate before calling

// Register once at executor creation so device loss is observed instead of surfacing as failed maps:
context.device.on_uncaptured_error(Box::new(|err| log::error!("wgpu error: {err:?}")));
// Before a large batch readback, drain pending device work so failures surface early:
let _ = context.device.poll(wgpu::wgt::PollType::wait_indefinitely());

Try / catch

use futures::FutureExt;
let result = std::panic::AssertUnwindSafe(convert_list(gpu_rasters, executor))
    .catch_unwind()
    .await;
match result {
    Ok(Ok(rasters)) => { /* success */ }
    Ok(Err(_)) | Err(_) => {
        // likely device loss: re-create the WgpuExecutor, then retry the batch once (or degrade to CPU processing)
    }
}

Prevention

When it happens

Trigger: Batch GPU-to-CPU conversion where any converter.convert() returns Err: the wgpu device was lost mid-readback (driver reset, adapter removed), a readback buffer was invalidated or dropped before its map completed, a map_async was rejected due to invalid buffer state, or the per-converter receiver.await failed while delivering the map result.

Common situations: GPU driver crash or adapter hot-unplug during export of many images; very large batch downloads racing with shutdown/teardown so buffers are freed while maps are pending; wgpu version upgrades changing map/poll semantics; CI or VM environments with flaky software adapters (lavapipe/LLVMpipe).

Related errors


AI-assisted analysis of GraphiteEditor/Graphite@c507b35645 (2026-08-16). Data as JSON: /api/errors/b3272e0a49bd81a6. Report an issue: GitHub.