rustdesk/rustdesk · error · anyhow::Error
encoder type mismatch
Error message
encoder type mismatch
What it means
VpxEncoder::new (libs/scrap/src/common/vpxcodec.rs) accepts only EncoderCfg::VPX(config); the catch-all arm returns 'encoder type mismatch'. Same constructor-level variant check pattern used by AomEncoder and HwRamEncoder: the EncoderCfg enum variant must correspond to the concrete encoder type being constructed.
Source
Thrown at libs/scrap/src/common/vpxcodec.rs:170
VP9E_SET_TILE_COLUMNS as _,
4 as c_int
));
} else if config.codec == VpxVideoCodecId::VP8 {
// https://github.com/webmproject/libvpx/blob/972149cafeb71d6f08df89e91a0130d6a38c4b15/vpx/vp8cx.h#L172
// https://groups.google.com/a/webmproject.org/g/webm-discuss/c/DJhSrmfQ61M
call_vpx!(vpx_codec_control_(&mut ctx, VP8E_SET_CPUUSED as _, 12,));
}
Ok(Self {
ctx,
width: config.width as _,
height: config.height as _,
id: config.codec,
i444,
yuvfmt: Self::get_yuvfmt(config.width, config.height, i444),
})
}
_ => Err(anyhow!("encoder type mismatch")),
}
}
fn encode_to_message(&mut self, input: EncodeInput, ms: i64) -> ResultType<VideoFrame> {
let mut frames = Vec::new();
for ref frame in self
.encode(ms, input.yuv()?, STRIDE_ALIGN)
.with_context(|| "Failed to encode")?
{
frames.push(VpxEncoder::create_frame(frame));
}
for ref frame in self.flush().with_context(|| "Failed to flush")? {
frames.push(VpxEncoder::create_frame(frame));
}
// to-do: flush periodically, e.g. 1 second
if frames.len() > 0 {
Ok(VpxEncoder::create_video_frame(self.id, frames))View on GitHub (pinned to 7aa98d43cf)
Solutions
- Route only EncoderCfg::VPX to VpxEncoder; check the creation dispatch (codec id -> EncoderCfg variant -> encoder struct).
- Make the dispatch match exhaustive over EncoderCfg so the compiler flags missing routes.
- Add a regression test per codec id asserting the returned encoder's type.
Example fix
// before
let enc = VpxEncoder::new(cfg, i444)?; // cfg is EncoderCfg::AOM -> 'encoder type mismatch'
// after
match cfg {
EncoderCfg::VPX(c) => Box::new(VpxEncoder::new(EncoderCfg::VPX(c), i444)?),
EncoderCfg::AOM(c) => Box::new(AomEncoder::new(EncoderCfg::AOM(c), i444)?),
EncoderCfg::HWRAM(c) => Box::new(HwRamEncoder::new(EncoderCfg::HWRAM(c), i444)?),
} Defensive patterns
Strategy: type-guard
Validate before calling
if !matches!(cfg, EncoderCfg::VPX(_)) {
return Err(anyhow!("VpxEncoder requires EncoderCfg::VPX"));
} Type guard
fn is_vpx_cfg(cfg: &EncoderCfg) -> bool {
matches!(cfg, EncoderCfg::VPX(_))
} Prevention
- Maintain a single exhaustive codec-dispatch match; no '_' arms.
- When adding encoders (AOM, HWRAM), wire them into the same match in one change.
- Cover the dispatch with unit tests per codec id.
When it happens
Trigger: Constructing VpxEncoder with EncoderCfg::AOM or EncoderCfg::HWRAM — dispatch layer mapped the negotiated codec (AV1 or hardware) to the libvpx encoder struct.
Common situations: Codec-selection refactors; new EncoderCfg variants added without updating the match in the creation layer; defaults that assume VPX everywhere.
Related errors
- encoder type mismatch
- encoder type mismatch
- no valid frame
- no valid frame
- failed to get format from name:{}
AI-assisted analysis of rustdesk/rustdesk@7aa98d43cf (2026-08-16).
Data as JSON: /api/errors/bc420c4ef17cb5de.
Report an issue: GitHub.