FyroxEngine/Fyrox · error

A brush painting message was not sent.

Error message

A brush painting message was not sent. {error:?}

What it means

Terrain brush painting communicates with a background worker thread via a channel; on_send_failure is the unwrap_or_else handler invoked when sending a BrushThreadMessage fails (receiver dropped). It logs that the painting command was not delivered.

Solutions

  1. Ensure the terrain and its brush thread outlive all brush painting calls (don't drop/destroy terrain mid-stroke).
  2. Check earlier logs for a brush worker panic that terminated the receiving thread.
  3. Guard brush UI/input handling so strokes end (finish_stroke) before terrain teardown.
Defensive patterns

Strategy: fallback

Validate before calling

// Before painting, verify the terrain handle still points to a live node with an active brush:
if let Some(terrain) = scene.graph.try_get(terrain_handle).ok() {
    terrain.paint(brush, stroke);
}

Prevention

When it happens

Trigger: BrushStroke operations (apply/commit/reset) calling message send on the brush thread channel after the worker thread has exited, producing SendError<BrushThreadMessage> handled by on_send_failure.

Common situations: Terrain destroyed or brush worker shut down while painting is still in progress; editor shutdown racing an in-flight stroke; a panic previously killed the worker thread.

Related errors


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

Appendix: source

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

    }
    /// Draw a pixel using the brush that was set in the most recent call to [BrushSender::start_stroke].
    #[inline]
    pub fn draw_pixel(&self, position: Vector2<i32>, alpha: f32, value: f32) {
        if alpha == 0.0 {
            return;
        }
        self.0
            .send(BrushThreadMessage::Pixel(BrushPixelMessage {
                position,
                alpha,
                value,
            }))
            .unwrap_or_else(on_send_failure);
    }
}

fn on_send_failure(error: SendError<BrushThreadMessage>) {
    Log::err(format!("A brush painting message was not sent. {error:?}"));
}

/// Type for a callback that delivers the original data of textures that have been modified
/// by the brush so that changes might be undone.
pub type UndoChunkHandler = dyn FnMut(UndoData) + Send;

/// A record of original data data for chunks that have been modified by a brushstroke.
pub struct UndoData {
    /// The handle of the terrain being edited
    pub node: Handle<Node>,
    /// The data of the chunks as they were before the brushstroke.
    pub chunks: Vec<ChunkData>,
    /// The kind of data within the terrain that is being edited.
    pub target: BrushTarget,
}

#[derive(Default)]
/// Data for an in-progress terrain painting operation

View on GitHub (pinned to 76c91aad8e)