{"record":{"id":"06b83a471cd13874","repo":"FyroxEngine/Fyrox","slug":"illegal-nine-slice-position-position","errorCode":null,"errorMessage":"Illegal nine slice position: {position:?}","messagePattern":"Illegal nine slice position: (.+?)","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"fyrox-impl/src/scene/tilemap/property.rs","lineNumber":554,"sourceCode":"            TileSetPropertyValue::NineSlice(_) => {\n                TileSetPropertyValue::NineSlice(Default::default())\n            }\n        }\n    }\n    /// The type of the data in this value.\n    pub fn prop_type(&self) -> TileSetPropertyType {\n        match self {\n            TileSetPropertyValue::I32(_) => TileSetPropertyType::I32,\n            TileSetPropertyValue::F32(_) => TileSetPropertyType::F32,\n            TileSetPropertyValue::String(_) => TileSetPropertyType::String,\n            TileSetPropertyValue::NineSlice(_) => TileSetPropertyType::NineSlice,\n        }\n    }\n    /// Converts an x,y position into index in 0..9. Both x and y must be within 0..3.\n    #[inline]\n    pub fn nine_position_to_index(position: Vector2<usize>) -> usize {\n        if position.y > 2 || position.x > 2 {\n            panic!(\"Illegal nine slice position: {position:?}\");\n        }\n        position.y * 3 + position.x\n    }\n    /// Converts an index in 0..9 into an x,y position within a tile's nine slice value.\n    #[inline]\n    pub fn index_to_nine_position(index: usize) -> Vector2<usize> {\n        let (y, x) = index.div_rem_euclid(&3);\n        Vector2::new(x, y)\n    }\n    /// Update this value to match the given value, wherever that value is not None.\n    /// Wherever the given value is None, no change is made to this value.\n    pub fn set_from(&mut self, value: &TileSetPropertyOptionValue) {\n        use TileSetPropertyOptionValue as OptValue;\n        use TileSetPropertyValue as PropValue;\n        match (self, value) {\n            (PropValue::I32(x0), OptValue::I32(Some(x1))) => *x0 = *x1,\n            (PropValue::F32(x0), OptValue::F32(Some(x1))) => *x0 = *x1,\n            (PropValue::String(x0), OptValue::String(Some(x1))) => *x0 = x1.clone(),","sourceCodeStart":536,"sourceCodeEnd":572,"githubUrl":"https://github.com/FyroxEngine/Fyrox/blob/76c91aad8eca488ce527b1af707be8b3b24ad72d/fyrox-impl/src/scene/tilemap/property.rs#L536-L572","documentation":"TileDefinition nine-slice handling: nine_position_to_index converts an (x,y) position in the 0..=2 range into an index in 0..9, and panics with \"Illegal nine slice position\" if either coordinate exceeds 2. Nine slices are 3x3 grids; any component >= 3 has no corresponding index.","triggerScenarios":"Calling nine_position_to_index(Vector2::new(x, y)) with x or y greater than 2; computing a nine-slice position from tile neighbours without clamping to the 3x3 grid.","commonSituations":"Custom tile-map brushes computing offsets from neighbor deltas without wrapping/clamping; autotiling code that maps edge configurations to nine-slice coordinates incorrectly; off-by-one loops over 0..=3 instead of 0..=2.","solutions":["Clamp the position components before calling: position.x.min(2) and position.y.min(2), or validate 0..=2 yourself.","Fix the source of the coordinate so it is derived via index_to_nine_position or bounded loops (for y in 0..3, for x in 0..3).","Add an assertion/validation on your computed position and fall back to the center cell (1,1) when out of range.","Use index_to_nine_position to round-trip and confirm your mapping is symmetric with this function."],"exampleFix":"// before\nlet idx = TileDefinition::nine_position_to_index(Vector2::new(dx + 1, dy + 1)); // dx may be ±2\n// after\nlet px = (dx + 1).clamp(0, 2);\nlet py = (dy + 1).clamp(0, 2);\nlet idx = TileDefinition::nine_position_to_index(Vector2::new(px, py));","handlingStrategy":"validation","validationCode":"fn valid_nine_position(p: Vector2<usize>) -> bool {\n    p.x <= 2 && p.y <= 2\n}\n// call site\nlet p = Vector2::new(px, py);\nif valid_nine_position(p) {\n    let idx = TileDefinition::nine_position_to_index(p);\n}","typeGuard":"fn is_nine_position(p: Vector2<usize>) -> bool {\n    p.x < 3 && p.y < 3\n}","tryCatchPattern":"// Panics are unrecoverable here; clamp before the call instead\nlet idx = TileDefinition::nine_position_to_index(Vector2::new(\n    px.min(2),\n    py.min(2),\n));","preventionTips":["Derive nine-slice coordinates with bounded loops (0..3) or index_to_nine_position.","Clamp computed neighbour-offset coordinates to 0..=2 before conversion.","Add debug_assert!(is_nine_position(p)) in brush/autotile code.","Keep nine-slice mapping logic centralized instead of computing x*3+y ad hoc."],"tags":["panic","nine-slice","tilemap","rust"],"backgroundTag":"value-out-of-range","analyzedSha":"76c91aad8eca488ce527b1af707be8b3b24ad72d","analyzedAt":"2026-09-10T16:04:01.633Z","contentChangedAt":"2026-09-10T16:04:01.633Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}