{"record":{"id":"02dbe0af72d56c88","repo":"flxzt/rnote","slug":"patternstyle-try-from-u32-for-value-failed","errorCode":null,"errorMessage":"PatternStyle try_from::<u32>() for value {} failed","messagePattern":"PatternStyle try_from::<u32>\\(\\) for value (.+?) failed","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/rnote-engine/src/document/background.rs","lineNumber":50,"sourceCode":"    Dots,\n    #[serde(rename = \"isometric_grid\")]\n    IsometricGrid,\n    #[serde(rename = \"isometric_dots\")]\n    IsometricDots,\n}\n\nimpl Default for PatternStyle {\n    fn default() -> Self {\n        Self::Dots\n    }\n}\n\nimpl TryFrom<u32> for PatternStyle {\n    type Error = anyhow::Error;\n\n    fn try_from(value: u32) -> Result<Self, Self::Error> {\n        num_traits::FromPrimitive::from_u32(value).ok_or_else(|| {\n            anyhow::anyhow!(\"PatternStyle try_from::<u32>() for value {} failed\", value)\n        })\n    }\n}\n\n/// 3_f64.sqrt()\nconst SQRT_THREE: f64 = 1.7320508075688772;\n/// 3_f64.sqrt() / 2_f64\nconst HALF_SQRT_THREE: f64 = SQRT_THREE / 2_f64;\n/// 3_f64.sqrt() / 4_f64\nconst QUARTER_SQRT_THREE: f64 = SQRT_THREE / 4_f64;\n\nfn gen_hline_pattern(\n    bounds: Aabb,\n    spacing: f64,\n    color: Color,\n    line_width: f64,\n) -> svg::node::element::Element {\n    let pattern_id = rnote_compose::utils::svg_random_id_prefix() + \"_bg_hline_pattern\";","sourceCodeStart":32,"sourceCodeEnd":68,"githubUrl":"https://github.com/flxzt/rnote/blob/bbc5354502ba2fc83eec2670b535348825e679a6/crates/rnote-engine/src/document/background.rs#L32-L68","documentation":"PatternStyle implements TryFrom<u32> via num_traits::FromPrimitive; any u32 that does not map to a defined PatternStyle variant produces this anyhow error. It guards deserialization of numeric enum values coming from saved documents or external input.","triggerScenarios":"Calling PatternStyle::try_from(u32) (or deserializing a document whose stored pattern-style integer is out of range or from a newer/older file format version with different variant numbering).","commonSituations":"Opening an .rnote file written by a different rnote version where enum discriminants shifted, hand-edited or corrupted files, and foreign code passing raw integers into the engine API.","solutions":["Check the u32 value against the defined PatternStyle variants before conversion.","Re-save/open the document with the rnote version that wrote it, so discriminants match.","If a format migration changed variant numbering, add a migration step mapping old integers to new variants.","Fall back to a default PatternStyle on conversion failure instead of propagating the error."],"exampleFix":"// before\nlet style = PatternStyle::try_from(raw_u32)?;\n// after\nlet style = PatternStyle::try_from(raw_u32)\n    .unwrap_or(PatternStyle::default());","handlingStrategy":"validation","validationCode":"fn is_valid_pattern_style(v: u32) -> bool {\n    PatternStyle::try_from(v).is_ok()\n}","typeGuard":"fn as_pattern_style(v: u32) -> Option<PatternStyle> {\n    num_traits::FromPrimitive::from_u32(v)\n}","tryCatchPattern":"match PatternStyle::try_from(raw) {\n    Ok(style) => style,\n    Err(e) => {\n        log::warn!(\"bad pattern style {raw}: {e}; using default\");\n        PatternStyle::default()\n    }\n}","preventionTips":["Never hand-craft enum integers; derive them from the enum itself","Add migrations when enum variants change between versions","Prefer serializing enums by name","Validate deserialized enum values with unit tests against saved documents"],"tags":["rust","enum","deserialization"],"backgroundTag":"invalid-enum-value","analyzedSha":"bbc5354502ba2fc83eec2670b535348825e679a6","analyzedAt":"2026-09-08T13:20:33.747Z","contentChangedAt":"2026-09-08T13:20:33.747Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}