wasmerio/wasmer · error

ExceptionRefs are not yet supported in the JS Function API

Error message

ExceptionRefs are not yet supported in the JS Function API

What it means

`as_jsvalue` turns a wasmer `Value` into a `JsValue` for the JS backend. ExceptionRef values have no JS representation in this backend yet, so the match arm calls `unimplemented!` and panics.

Source

Thrown at lib/api/src/backend/js/utils/convert.rs:116

    type DefinitionType = Type;

    fn as_jsvalue(&self, _store: &impl AsStoreRef) -> JsValue {
        match self {
            Self::I32(i) => JsValue::from(*i),
            Self::I64(i) => JsValue::from(*i),
            Self::F32(f) => JsValue::from(*f),
            Self::F64(f) => JsValue::from(*f),
            Self::V128(v) => JsValue::from(*v),
            Self::FuncRef(Some(func)) => func.as_js().handle.function.clone().into(),
            Self::FuncRef(None) => JsValue::null(),
            Self::ExternRef(Some(reference)) => match &reference.0 {
                crate::BackendExternRef::Js(reference) => reference.as_js_value(),
                #[allow(unreachable_patterns)]
                _ => unreachable!("a JS function received an externref from another backend"),
            },
            Self::ExternRef(None) => JsValue::null(),
            Self::ExceptionRef(_) => {
                unimplemented!("ExceptionRefs are not yet supported in the JS Function API",)
            }
        }
    }

    fn from_jsvalue(
        store: &mut impl AsStoreMut,
        type_: &Self::DefinitionType,
        value: &JsValue,
    ) -> Result<Self, JsError> {
        Ok(js_value_to_wasmer(store, type_, value))
    }
}

impl AsJs for Imports {
    type DefinitionType = crate::module::Module;

    // Annotation is here to prevent spurious IDE warnings.
    #[allow(unused_unsafe)]

View on GitHub (pinned to 8c4b9ee9d3)

Solutions

  1. Do not store/transfer ExceptionRef values on the js backend; keep payloads as numeric or externref values
  2. Handle exceptions only at the host boundary and never round-trip ExceptionRef through JS
  3. Use a native backend with exception-handling support if exceptionrefs are required

Example fix

// before
Value::ExceptionRef(e) // passed to JS -> panics
// after
Value::I32(e.as_i32_handle()) // serialize payload to an integer
Defensive patterns

Strategy: type-guard

Validate before calling

fn js_convertible(v: &Value) -> bool {
    !matches!(v, Value::ExceptionRef(_))
}

Type guard

fn js_convertible(v: &Value) -> bool {
    !matches!(v, Value::ExceptionRef(_))
}

Try / catch

if let Value::ExceptionRef(_) = v {
    return Err(anyhow!("ExceptionRef cannot cross the JS boundary"));
}

Prevention

When it happens

Trigger: Converting any `Value::ExceptionRef(_)` (or `Value::ExceptionRef` in a value list) to a JsValue — e.g. when passing exception-tag payloads or results through the JS function API on the js backend.

Common situations: Exception-handling experiments that attach exceptionref payloads; shared code paths that work on native runtimes but hit the stub in the browser.

Related errors


AI-assisted analysis of wasmerio/wasmer@8c4b9ee9d3 (2026-09-01). Data as JSON: /api/errors/faf76747c639ab63. Report an issue: GitHub.