FyroxEngine/Fyrox · error

Tile data swap error

Error message

Tile data swap error

What it means

TileDataUpdate::swap_with_data swaps the update's payload with a TileData value. It is called when the update variant carries per-tile data (MaterialTile/FreeformTile/Property). If the variant is Erase (or another non-data variant) it cannot swap anything, so the engine logs this error and downgrades the update to DoNothing to keep the update list consistent.

Solutions

  1. Ensure only MaterialTile, FreeformTile, or Property (with payload) updates are passed to swap_with_data
  2. Send Erase updates through the normal tile-set erase path instead of the data-swap path
  3. Check for logic that appends Erase updates where data updates were intended

Example fix

// before
update.swap_with_data(&mut tile_data); // update may be Erase
// after
if matches!(update, TileDataUpdate::MaterialTile(_) | TileDataUpdate::FreeformTile(_) | TileDataUpdate::Property(..)) {
    update.swap_with_data(&mut tile_data);
}
Defensive patterns

Strategy: validation

Validate before calling

if matches!(update, TileDataUpdate::Erase | TileDataUpdate::DoNothing | TileDataUpdate::TransformSet(_) | TileDataUpdate::Material(_)) {
    return; // do not call swap_with_data
}
update.swap_with_data(&mut tile_data);

Type guard

fn can_swap(u: &TileDataUpdate) -> bool {
    matches!(u, TileDataUpdate::MaterialTile(_) | TileDataUpdate::FreeformTile(_) | TileDataUpdate::Property(..))
}

Prevention

When it happens

Trigger: Calling swap_with_data on a TileDataUpdate that is TileDataUpdate::Erase; this happens in tilemap update processing when an erase-marker update is applied against tile data.

Common situations: Custom tilemap tooling or editor plugins that construct TileDataUpdate sequences manually and mix Erase updates with data swaps; applying recorded tile updates from a stale or mismatched update batch.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


AI-assisted analysis of FyroxEngine/Fyrox@76c91aad8e (2026-09-10). Data as JSON: /api/errors/aff15d8b4cd5f757. Report an issue: GitHub.

Appendix: source

Thrown at fyrox-impl/src/scene/tilemap/update.rs:291

        match std::mem::take(self) {
            TileDataUpdate::MaterialTile(d) => d,
            _ => panic!(),
        }
    }
    /// Remove `TileDefinition` and turn this object into `Erase`, if this is a FreeformTile. Otherwise, panic.
    pub fn take_definition(&mut self) -> TileDefinition {
        match std::mem::take(self) {
            TileDataUpdate::FreeformTile(d) => d,
            _ => panic!(),
        }
    }
    /// Swap whatever value is in this tile update with the corresponding value in the given TileData.
    /// If this update has no data to swap, then do nothing and set this update to `DoNothing`.
    pub fn swap_with_data(&mut self, data: &mut TileData) {
        match self {
            TileDataUpdate::DoNothing => (),
            TileDataUpdate::Erase => {
                Log::err("Tile data swap error");
                *self = Self::DoNothing;
            }
            TileDataUpdate::MaterialTile(tile_data) => std::mem::swap(tile_data, data),
            TileDataUpdate::FreeformTile(tile_definition) => {
                std::mem::swap(&mut tile_definition.data, data)
            }
            TileDataUpdate::Color(color) => std::mem::swap(color, &mut data.color),
            TileDataUpdate::Collider(colliders) => {
                for (uuid, value) in colliders.iter_mut() {
                    match data.colliders.entry(*uuid) {
                        Entry::Occupied(mut e) => {
                            if let TileCollider::None = value {
                                *value = e.remove();
                            } else {
                                std::mem::swap(e.get_mut(), value)
                            }
                        }
                        Entry::Vacant(e) => {

View on GitHub (pinned to 76c91aad8e)