{"record":{"id":"be952c9508236cc3","repo":"GraphiteEditor/Graphite","slug":"failed-to-download-texture-data","errorCode":null,"errorMessage":"Failed to download texture data","messagePattern":"Failed to download texture data","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"node-graph/libraries/wgpu-executor/src/texture_conversion.rs","lineNumber":246,"sourceCode":"\t\t\t.collect()\n\t}\n}\n\n/// Converts single GPU raster to CPU by downloading texture data\nimpl<'i> Convert<Raster<CPU>, &'i WgpuExecutor> for Raster<GPU> {\n\tasync fn convert(self, _: Footprint, executor: &'i WgpuExecutor) -> Raster<CPU> {\n\t\tlet device = &executor.context().device;\n\t\tlet queue = &executor.context().queue;\n\n\t\tlet mut encoder = device.create_command_encoder(&wgpu::CommandEncoderDescriptor {\n\t\t\tlabel: Some(\"single_texture_download_encoder\"),\n\t\t});\n\n\t\tlet converter = RasterGpuToRasterCpuConverter::new(device, &mut encoder, self);\n\n\t\tqueue.submit([encoder.finish()]);\n\n\t\tconverter.convert(device).await.expect(\"Failed to download texture data\")\n\t}\n}\n","sourceCodeStart":228,"sourceCodeEnd":249,"githubUrl":"https://github.com/GraphiteEditor/Graphite/blob/c507b356453361e31638b8bff8f6d46b6da2961e/node-graph/libraries/wgpu-executor/src/texture_conversion.rs#L228-L249","documentation":"The single-texture download path (texture_conversion.rs:233) submits a copy encoder, then the converter maps its readback buffer by polling the device and awaiting the map_async result over a channel; converter.convert(device).await returns Err when that map is rejected, and .expect(\"Failed to download texture data\") panics. It is the single-raster variant of the batch failure at line 219, with the same wgpu root causes.","triggerScenarios":"Downloading one GPU texture to a CPU raster when the device is lost (driver reset), when the readback buffer is invalid or dropped before the map completes, when map_async is rejected due to the buffer's state, or when the channel delivering the map result breaks during executor teardown.","commonSituations":"Exporting or screenshotting a single rendered image immediately after heavy GPU work; running under remote desktop/VM software adapters; wgpu upgrades; downloads issued while the editor/executor is being torn down (document closed mid-evaluation).","solutions":["Determine whether the device was lost: enable wgpu logging / uncaptured-error handler; on device loss, re-create the executor and retry the download once","Keep the converter and its buffer alive until convert() resolves; do not free GPU resources during pending maps","Replace .expect with error propagation so callers can retry or report a user-visible failure","If reproducible for specific textures, check them for extreme dimensions or formats that make the copy/readback invalid"],"exampleFix":"// before\nconverter.convert(device).await.expect(\"Failed to download texture data\")\n\n// after\nconverter.convert(device).await.map_err(|_| TextureDownloadError::MapFailed)? // caller re-creates the executor on device loss, then retries","handlingStrategy":"retry","validationCode":"// Before downloading, confirm the texture is non-degenerate and the device is responsive:\nassert!(texture.width() > 0 && texture.height() > 0);\nlet _ = device.poll(wgpu::wgt::PollType::wait_indefinitely()); // surfaces queued errors early","typeGuard":null,"tryCatchPattern":"use futures::FutureExt;\nlet attempt = std::panic::AssertUnwindSafe(raster_gpu.convert(footprint, executor)).catch_unwind().await;\nmatch attempt {\n    Ok(cpu) => { /* success */ }\n    Err(_) => { /* re-create the executor (device loss is the usual cause) and retry the download once */ }\n}","preventionTips":["Do not issue texture downloads while the executor/device is being torn down (document close, app exit)","Log wgpu uncaptured errors and device-lost callbacks so the root cause is visible before this panic","On flaky VM/software adapters, wrap single downloads with one retry"],"tags":["rust","wgpu","gpu","texture","readback","panic"],"backgroundTag":"wgpu-buffer-map-failed","analyzedSha":"c507b356453361e31638b8bff8f6d46b6da2961e","analyzedAt":"2026-08-16T21:57:18.596Z","schemaVersion":2},"datasetVersion":"2026-08-16T23:17:17.608Z"}