{"record":{"id":"363bece9057b6e9e","repo":"rustdesk/rustdesk","slug":"failed-to-create-decoder","errorCode":null,"errorMessage":"Failed to create decoder","messagePattern":"Failed to create decoder","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"libs/scrap/src/common/hwcodec.rs","lineNumber":363,"sourceCode":"        info\n    }\n\n    pub fn new(format: CodecFormat) -> ResultType<Self> {\n        let info = HwRamDecoder::try_get(format);\n        log::info!(\"try create {info:?} ram decoder\");\n        let Some(info) = info else {\n            bail!(\"unsupported format: {:?}\", format);\n        };\n        let ctx = DecodeContext {\n            name: info.name.clone(),\n            device_type: info.hwdevice.clone(),\n            thread_count: codec_thread_num(16) as _,\n        };\n        match Decoder::new(ctx) {\n            Ok(decoder) => Ok(HwRamDecoder { decoder, info }),\n            Err(_) => {\n                HwCodecConfig::clear(false, false);\n                Err(anyhow!(format!(\"Failed to create decoder\")))\n            }\n        }\n    }\n    pub fn decode<'a>(&'a mut self, data: &[u8]) -> ResultType<Vec<HwRamDecoderImage<'a>>> {\n        match self.decoder.decode(data) {\n            Ok(v) => Ok(v.iter().map(|f| HwRamDecoderImage { frame: f }).collect()),\n            Err(e) => Err(anyhow!(e)),\n        }\n    }\n}\n\npub struct HwRamDecoderImage<'a> {\n    frame: &'a DecodeFrame,\n}\n\nimpl HwRamDecoderImage<'_> {\n    // rgb [in/out] fmt and stride must be set in ImageRgb\n    pub fn to_fmt(&self, rgb: &mut ImageRgb, i420: &mut Vec<u8>) -> ResultType<()> {","sourceCodeStart":345,"sourceCodeEnd":381,"githubUrl":"https://github.com/rustdesk/rustdesk/blob/7aa98d43cf1962a7a29ec16ffef42974377ef11e/libs/scrap/src/common/hwcodec.rs#L345-L381","documentation":"HwRamDecoder::new found a CodecInfo for the requested format (info was Some) but hwcodec's Decoder::new(ctx) failed to instantiate it. As a side effect HwCodecConfig::clear(false, false) wipes the cached hardware config so the next detection re-probes, then 'Failed to create decoder' returns. The underlying cause is dropped by map_err, so only the generic message survives.","triggerScenarios":"Decoder open fails although it was listed: driver/session limits (max concurrent decode sessions on NVDEC/vaapi), device lost/reset, unsupported profile of the incoming stream, or a stale detection cache pointing at a device that no longer exists.","commonSituations":"Multiple simultaneous sessions exhausting hardware decode slots; GPU driver update or TDR reset between detection and creation; running in containers without GPU device access; virtual machines.","solutions":["Log the discarded inner error (keep e in the anyhow! message) to see the driver's refusal reason.","Retry creation once after HwCodecConfig::clear has invalidated the cache (the code already clears it for you).","Fall back to software decoding for this stream (vpx path) when hardware decode creation fails.","Check concurrency: close other decode sessions or reduce the number of simultaneous video streams."],"exampleFix":"// before\nErr(_) => {\n    HwCodecConfig::clear(false, false);\n    Err(anyhow!(format!(\"Failed to create decoder\")))\n}\n\n// after\nErr(e) => {\n    HwCodecConfig::clear(false, false);\n    Err(anyhow!(\"Failed to create decoder: {}\", e))\n}","handlingStrategy":"retry","validationCode":"// confirm the decoder device can actually open before the session\nlet info = hwcodec::Decoder::info(0, is_hevc).ok_or_else(|| anyhow!(\"no hw decoder listed\"))?;\nlet probe = hwcodec::Decoder::new(DecodeContext { name: info.name.clone(), device_type: info.hwdevice.clone(), thread_count: 1 });","typeGuard":null,"tryCatchPattern":"match Decoder::new(ctx) {\n    Ok(decoder) => Ok(HwRamDecoder { decoder, info }),\n    Err(e) => { HwCodecConfig::clear(false, false); Err(anyhow!(\"Failed to create decoder: {}\", e)) }\n}","preventionTips":["Keep the inner error string — driver refusal reasons are the key diagnostic.","Re-probe once after HwCodecConfig::clear; the clear already invalidates a stale cache.","Bound concurrent hardware decode sessions per process; fall back to software decode when limits hit."],"tags":["decoder","hwcodec","gpu","driver","error-context"],"backgroundTag":null,"analyzedSha":"7aa98d43cf1962a7a29ec16ffef42974377ef11e","analyzedAt":"2026-08-16T06:17:34.842Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}