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

  1. Inspect typeof window.sendNativeMessage in the failing page to see what occupies the name
  2. Use dyn_ref::<Function>() and log the actual type before calling
  3. 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

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


AI-assisted analysis of GraphiteEditor/Graphite@c507b35645 (2026-08-16). Data as JSON: /api/errors/bc3d8b0537de7eed. Report an issue: GitHub.