GraphiteEditor/Graphite · error
Not a function
Error message
Not a function
What it means
The wrapper found a property named sendNativeMessage on the JS global, but dyn_into::<js_sys::Function>() failed because the value is not callable. Existence and callability are separate checks in this code, and this panic is the second one failing: the name is occupied by a non-function value.
Source
Thrown at frontend/wrapper/src/native_communication.rs:92
pub fn initialize_native_communication() {
let global = js_sys::global();
// Get the function by name
let func = js_sys::Reflect::get(&global, &JsValue::from_str("initializeNativeCommunication")).expect("Function not found");
let func = func.dyn_into::<js_sys::Function>().expect("Not a function");
// Call it
func.call0(&JsValue::NULL).expect("Function call failed");
}
pub fn send_message_to_cef(message: String) {
let global = js_sys::global();
// Get the function by name
let func = js_sys::Reflect::get(&global, &JsValue::from_str("sendNativeMessage")).expect("Function not found");
let func = func.dyn_into::<js_sys::Function>().expect("Not a function");
let array = Uint8Array::from(message.as_bytes());
let buffer = array.buffer();
// Call it with argument
func.call1(&JsValue::NULL, &JsValue::from(buffer)).expect("Function call failed");
}
#[cfg(feature = "editor")]
pub(crate) use editor::messages::frontend::utility_types::RasterizedImage;
#[cfg(not(feature = "editor"))]
pub(crate) use RasterizedImageCopy as RasterizedImage;
#[cfg(any(not(feature = "editor"), test))]
#[derive(serde::Deserialize)]
pub(crate) struct RasterizedImageCopy {
pub(crate) id: u64,
pub(crate) width: u32,View on GitHub (pinned to c507b35645)
Solutions
- Inspect typeof window.sendNativeMessage in the failing page to see what occupies the name
- Use dyn_ref::<Function>() and log the actual type before calling
- Namespace the bridge globals (for example __graphiteSendNativeMessage) so page scripts cannot collide
Example fix
// before
let func = func.dyn_into::<js_sys::Function>().expect("Not a function");
// after
let Some(func) = found.dyn_ref::<js_sys::Function>().cloned() else {
error!("sendNativeMessage has unexpected type: {:?}", found.js_typeof());
return;
}; Defensive patterns
Strategy: type-guard
Validate before calling
// host page: assert the name is actually a function before the wasm sends // console.assert(typeof window.sendNativeMessage === 'function')
Type guard
fn as_function(value: &JsValue) -> Option<js_sys::Function> {
value.dyn_ref::<js_sys::Function>().cloned()
} Prevention
- Namespace bridge globals so page scripts cannot shadow them
- Check js_typeof before every dyn_into on host-provided values
- Assign bridge functions in one atomic script load rather than progressive stubbing
When it happens
Trigger: Another script defining window.sendNativeMessage as non-function data (name collision); a placeholder or stub object assigned before the real function loads; a partially initialized bridge leaving a module object instead of a function.
Common situations: Page scripts, analytics, or bundler shims claiming generic global names; older bridge versions assigning state objects; third-party code on the same page in the CEF shell.
Related errors
- Function not found
- Function call failed
- Failed to spawn the CEF control thread
- The CEF control thread ended without a result
- Failed to connect to the main process bootstrap server
AI-assisted analysis of GraphiteEditor/Graphite@c507b35645 (2026-08-16).
Data as JSON: /api/errors/bc3d8b0537de7eed.
Report an issue: GitHub.