wasmerio/wasmer · error

The type `{:?}` is not yet supported in the JS Function API

Error message

The type `{:?}` is not yet supported in the JS Function API

What it means

`js_value_to_wasmer` converts JS values into wasmer `Value`s when calling imported JS functions from wasm. `FuncRef` and `ExceptionRef` parameter/result types have no conversion implemented on the JS backend, so encountering one panics with this message.

Source

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

        Type::F32 => Value::F32(js_val.as_f64().unwrap() as _),
        Type::F64 => Value::F64(js_val.as_f64().unwrap()),
        Type::V128 => {
            let big_num: u128 = js_sys::BigInt::from(js_val.clone()).try_into().unwrap();
            Value::V128(big_num)
        }
        Type::ExternRef => {
            if js_val.is_null() {
                Value::ExternRef(None)
            } else {
                Value::ExternRef(Some(crate::ExternRef(crate::BackendExternRef::Js(
                    crate::backend::js::entities::external::ExternRef::from_js_value(
                        store,
                        js_val.clone(),
                    ),
                ))))
            }
        }
        Type::FuncRef | Type::ExceptionRef => unimplemented!(
            "The type `{:?}` is not yet supported in the JS Function API",
            ty
        ),
    }
}

#[inline]
/// Convert a wasmer Value into a JsValue
pub fn wasmer_value_to_js(val: &Value) -> JsValue {
    match val {
        Value::I32(i) => JsValue::from_f64(*i as _),
        Value::I64(i) => JsValue::from_f64(*i as _),
        Value::F32(f) => JsValue::from_f64(*f as _),
        Value::F64(f) => JsValue::from_f64(*f),
        Value::V128(f) => JsValue::from_f64(*f as _),
        Value::ExternRef(Some(reference)) => match &reference.0 {
            crate::BackendExternRef::Js(reference) => reference.as_js_value(),
            #[allow(unreachable_patterns)]

View on GitHub (pinned to 8c4b9ee9d3)

Solutions

  1. Change import signatures to avoid FuncRef/ExceptionRef at the JS boundary (pass numeric indices/handles instead)
  2. Wrap the JS side so functions are exchanged through a host-side registry keyed by i32
  3. Use a native backend if funcref-typed imports are a hard requirement

Example fix

// before
let ty = FunctionType::new(vec![Type::FuncRef], vec![]);
// after
let ty = FunctionType::new(vec![Type::I32], vec![]); // pass funcref as registry index
Defensive patterns

Strategy: validation

Validate before calling

fn js_function_sig_supported(ft: &FunctionType) -> bool {
    ft.params().iter().chain(ft.results()).all(
        |t| !matches!(t, Type::FuncRef | Type::ExceptionRef))
}

Try / catch

if !js_function_sig_supported(&func_ty) {
    return Err(anyhow!("funcref/exceptionref not supported by js Function API"));
}
let f = Function::new_with_env(&mut store, &import_ty, env, callback);

Prevention

When it happens

Trigger: Calling (sync or async) a JS-function import whose signature includes `Type::FuncRef` or `Type::ExceptionRef` parameters or results — via `Function::new_with_env`, `new_with_env_async`, or `Function::call`/`call_async` on the js backend.

Common situations: Imports that pass callbacks (funcref) into JS or return exceptionrefs; works with native runtimes, panics when the same module runs in the browser.

Related errors


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