flxzt/rnote · error

MeasureUnit try_from

Error message

MeasureUnit try_from::<u32>() for value {} failed

What it means

MeasureUnit implements TryFrom<u32> via num_traits::FromPrimitive; any u32 without a matching MeasureUnit variant produces this error. It validates numeric unit identifiers restored from saved preferences or documents.

Solutions

  1. Check the u32 against the defined MeasureUnit variants before conversion.
  2. Migrate enum values when loading files from older/newer rnote versions.
  3. Fall back to a default MeasureUnit (e.g. px or mm) when conversion fails.
  4. Serialize units by name rather than discriminant for forward compatibility.

Example fix

// before
let unit = MeasureUnit::try_from(raw_u32)?;
// after
let unit = MeasureUnit::try_from(raw_u32)
    .unwrap_or(MeasureUnit::default());
Defensive patterns

Strategy: validation

Validate before calling

fn is_valid_measure_unit(v: u32) -> bool {
    MeasureUnit::try_from(v).is_ok()
}

Type guard

fn as_measure_unit(v: u32) -> Option<MeasureUnit> {
    num_traits::FromPrimitive::from_u32(v)
}

Try / catch

match MeasureUnit::try_from(raw) {
    Ok(u) => u,
    Err(_) => {
        log::warn!("unknown measure unit {raw}; defaulting");
        MeasureUnit::default()
    }
}

Prevention

When it happens

Trigger: Calling MeasureUnit::try_from(u32) with an out-of-range value, usually during deserialization of format preferences (e.g. units stored as integers in .rnote files).

Common situations: Documents written by other rnote versions where unit enum ordering changed, corrupted files, or code passing raw integers received from external sources.

Understand the failure class

Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.

Related errors


AI-assisted analysis of flxzt/rnote@bbc5354502 (2026-09-08). Data as JSON: /api/errors/88aafd07f7396149. Report an issue: GitHub.

Appendix: source

Thrown at crates/rnote-engine/src/document/format.rs:109

    Px = 0,
    #[serde(rename = "mm")]
    Mm,
    #[serde(rename = "cm")]
    Cm,
}

impl Default for MeasureUnit {
    fn default() -> Self {
        Self::Px
    }
}

impl TryFrom<u32> for MeasureUnit {
    type Error = anyhow::Error;

    fn try_from(value: u32) -> Result<Self, Self::Error> {
        num_traits::FromPrimitive::from_u32(value).ok_or_else(|| {
            anyhow::anyhow!("MeasureUnit try_from::<u32>() for value {} failed", value)
        })
    }
}

impl MeasureUnit {
    pub const AMOUNT_MM_IN_INCH: f64 = 25.4;

    pub fn convert_measurement(
        value: f64,
        value_unit: MeasureUnit,
        value_dpi: f64,
        desired_unit: MeasureUnit,
        desired_dpi: f64,
    ) -> f64 {
        let value_in_px = match value_unit {
            MeasureUnit::Px => value,
            MeasureUnit::Mm => (value / Self::AMOUNT_MM_IN_INCH) * value_dpi,
            MeasureUnit::Cm => ((value * 10.0) / Self::AMOUNT_MM_IN_INCH) * value_dpi,

View on GitHub (pinned to bbc5354502)