FyroxEngine/Fyrox · error

Texture is not rectangle

Error message

Texture is not rectangle

What it means

Chunk::create_margin adds a 1px zero margin around the chunk's heightmap, but first requires the current heightmap texture to be TextureKind::Rectangle. If the texture has any other kind, it panics with "Texture is not rectangle". Like the other terrain panics, this guards the invariant that terrain heightmaps are 2D rectangle textures of f32 data.

Solutions

  1. Ensure the heightmap texture kind is TextureKind::Rectangle (build it with make_height_map_texture) before calling create_margin.
  2. Verify data.kind() matches TextureKind::Rectangle before calling create_margin and rebuild the heightmap otherwise.
  3. Use the standard terrain construction path (TerrainBuilder / chunk height data editing) which already maintains correct texture kinds.
  4. If margins are the goal, prefer building the heightmap with margin included up front instead of post-hoc create_margin on foreign textures.

Example fix

// before
chunk.set_height_map(my_non_rectangle_texture);
chunk.create_margin(); // panics
// after
assert!(matches!(my_tex.data_ref().kind(), TextureKind::Rectangle { .. }));
chunk.set_height_map(my_tex);
chunk.create_margin();
Defensive patterns

Strategy: validation

Validate before calling

let data = chunk.height_map().unwrap().data_ref();
assert!(matches!(data.kind(), TextureKind::Rectangle { .. }));
assert!(data.data_of_type::<f32>().is_some());
chunk.create_margin();

Type guard

fn can_create_margin(tex: &TextureResource) -> bool {
    let d = tex.data_ref();
    matches!(d.kind(), TextureKind::Rectangle { .. }) && d.data_of_type::<f32>().is_some()
}

Try / catch

// No recoverable catch for panics; validate first
if can_create_margin(&chunk.height_map().unwrap()) {
    chunk.create_margin();
} else {
    // regenerate the heightmap from source data
}

Prevention

When it happens

Trigger: Calling chunk.create_margin() on a chunk whose heightmap texture is not a Rectangle-kind texture (wrong TextureKind variant or missing/unset kind). Note it also unwraps data_of_type::<f32>(), so non-f32 heightmaps will additionally fail.

Common situations: Assigning a custom-built or image-loaded texture as a chunk heightmap and then calling create_margin; terrain code migrated from versions with different heightmap representations; procedural generation that skips the terrain texture helpers.

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 FyroxEngine/Fyrox@76c91aad8e (2026-09-10). Data as JSON: /api/errors/708f157ae5914437. Report an issue: GitHub.

Appendix: source

Thrown at fyrox-impl/src/scene/terrain/mod.rs:477

            layer_masks: Default::default(),
            height_map_modifications_count: 0,
        }
    }
}

impl Chunk {
    /// Return a view of the height data as a 2D array of f32.
    pub fn height_data(&self) -> ChunkHeightData {
        ChunkHeightData(self.heightmap.as_ref().map(|r| r.data_ref()).unwrap())
    }

    /// Modify the height texture of the chunk to give it a one pixel margin around all four edges.
    /// The [`Chunk::height_map_size`] is increased to match. The margin is initialized to zero.
    pub fn create_margin(&mut self) {
        let data = self.heightmap.as_ref().map(|r| r.data_ref()).unwrap();
        let size = match data.kind() {
            TextureKind::Rectangle { width, height } => Vector2::new(width, height),
            _ => panic!("Texture is not rectangle"),
        };
        let data_f32 = From::<&[f32]>::from(data.data_of_type().unwrap());
        let result = create_zero_margin(data_f32, size);
        drop(data);
        self.heightmap = Some(make_height_map_texture(result, size.map(|x| x + 2)));
        self.height_map_size = self.height_map_size.map(|x| x + 2);
    }
    /// Check the heightmap for modifications and update data as necessary.
    pub fn update(&self) {
        let Some(heightmap) = self.heightmap.as_ref() else {
            return;
        };
        let count = heightmap.data_ref().modifications_count();
        let mut quad_tree = self.quad_tree.safe_lock();
        if count != quad_tree.height_mod_count() {
            *quad_tree = make_quad_tree(&self.heightmap, self.height_map_size, self.block_size);
        }
    }

View on GitHub (pinned to 76c91aad8e)