FyroxEngine/Fyrox · warning

Failed to send script message, it means the scene is…

Error message

Failed to send script message, it means the scene is already deleted!

What it means

ScriptMessageSender wraps a channel whose receiver lives in a scene's script context. When the receiver has been dropped (scene deleted) the mpsc send fails; the engine logs this error and silently drops the message — the caller gets no error back.

Solutions

  1. Check that the scene is still alive before sending script messages
  2. Drop or invalidate cached ScriptMessageSender references when the scene is destroyed
  3. Defer teardown-sensitive messages until next frame and verify scene validity
  4. Treat the log line as a signal to audit scene lifetime management

Example fix

// before
script_sender.send_global(message); // scene may be gone
// after
if scene_handle.is_some() && engine.scenes.is_valid_handle(scene_handle) {
    script_sender.send_global(message);
}
Defensive patterns

Strategy: type-guard

Validate before calling

if !engine.scenes().is_valid_handle(scene_handle) { return; } // then send
script_sender.send_global(msg);

Type guard

fn scene_alive(engine: &Engine, h: Handle<Scene>) -> bool { engine.scenes.is_valid_handle(h) }

Try / catch

// send() does not return Result; watch logs instead
if !scene_alive(&engine, scene_handle) {
    // skip message or re-queue after scene rebuild
} else {
    script_sender.send_global(msg);
}

Prevention

When it happens

Trigger: Calling ScriptMessageSender::send / send_to_target / send_global / send_hierarchical after the owning scene was removed or is being destroyed.

Common situations: Deferred or queued script messages delivered after scene unload; background tasks or UI callbacks firing into a scene handle that no longer exists; sending during teardown ordering races.

Related errors


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

Appendix: source

Thrown at fyrox-impl/src/script/mod.rs:153

}

/// A script message sender.
#[derive(Clone)]
pub struct ScriptMessageSender {
    pub(crate) sender: Sender<ScriptMessage>,
}

impl Debug for ScriptMessageSender {
    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
        write!(f, "ScriptMessageSender")
    }
}

impl ScriptMessageSender {
    /// Send a generic script message.
    pub fn send(&self, message: ScriptMessage) {
        if self.sender.send(message).is_err() {
            Log::err("Failed to send script message, it means the scene is already deleted!");
        }
    }

    /// Sends a targeted script message with the given payload.
    pub fn send_to_target<T>(&self, target: Handle<impl ObjectOrVariant<Node>>, payload: T)
    where
        T: ScriptMessagePayload,
    {
        self.send(ScriptMessage {
            payload: Box::new(payload),
            kind: ScriptMessageKind::Targeted(target.transmute()),
        })
    }

    /// Sends a global script message with the given payload.
    pub fn send_global<T>(&self, payload: T)
    where
        T: ScriptMessagePayload,

View on GitHub (pinned to 76c91aad8e)