clockworklabs/SpacetimeDB · critical

{CALL_VIEW_ANON_DUNDER} export is not a function

Error message

{CALL_VIEW_ANON_DUNDER} export is not a function

What it means

get_call_view_anon resolves the `__call_view_anon__` export, the entry point for anonymous views. `Export::into_func()` returns None when that name is exported as a memory, global, or table, and the host panics because a non-function entry is unrecoverable. The export is optional (absent name yields None), so the panic only fires when something occupies the name with the wrong kind.

Source

Thrown at crates/core/src/host/wasmtime/wasmtime_module.rs:483

    let export = instance.get_export(store.as_context_mut(), CALL_VIEW_DUNDER)?;
    Some(
        export
            .into_func()
            .unwrap_or_else(|| panic!("{CALL_VIEW_DUNDER} export is not a function"))
            .typed(store)
            .unwrap_or_else(|err| panic!("{CALL_VIEW_DUNDER} export is a function with incorrect type: {err}")),
    )
}

/// Look up the `instance`'s export named by [`CALL_VIEW_ANON_DUNDER`].
///
/// Similar to [`get_call_procedure`], but for anonymous views.
fn get_call_view_anon(store: &mut Store<WasmInstanceEnv>, instance: &Instance) -> Option<CallViewAnonType> {
    let export = instance.get_export(store.as_context_mut(), CALL_VIEW_ANON_DUNDER)?;
    Some(
        export
            .into_func()
            .unwrap_or_else(|| panic!("{CALL_VIEW_ANON_DUNDER} export is not a function"))
            .typed(store)
            .unwrap_or_else(|err| panic!("{CALL_VIEW_ANON_DUNDER} export is a function with incorrect type: {err}")),
    )
}

/// Look up the `instance`'s export named by [`CALL_HTTP_HANDLER_DUNDER`].
///
/// Similar to [`get_call_procedure`], but for HTTP handlers.
fn get_call_http_handler(store: &mut Store<WasmInstanceEnv>, instance: &Instance) -> Option<CallHttpHandlerType> {
    let export = instance.get_export(store.as_context_mut(), CALL_HTTP_HANDLER_DUNDER)?;
    Some(
        export
            .into_func()
            .unwrap_or_else(|| panic!("{CALL_HTTP_HANDLER_DUNDER} export is not a function"))
            .typed(store)
            .unwrap_or_else(|err| panic!("{CALL_HTTP_HANDLER_DUNDER} export is a function with incorrect type: {err}")),
    )
}

View on GitHub (pinned to 6dee26c6ef)

Solutions

  1. Run `wasm-objdump -x module.wasm | grep -A2 __call_view_anon__` to identify the export kind.
  2. Rename or remove the conflicting export in module source and rebuild.
  3. Regenerate the module with the official SDK so only functions carry the dunder names.
Defensive patterns

Strategy: type-guard

Validate before calling

use wasmtime::{Engine, Module, ExternType};

fn anon_view_export_is_func(engine: &Engine, wasm: &[u8]) -> Result<(), String> {
    let module = Module::new(engine, wasm).map_err(|e| e.to_string())?;
    if let Some(exp) = module.get_export("__call_view_anon__") {
        if !matches!(exp.ty(), ExternType::Func(_)) {
            return Err(format!("__call_view_anon__ exported as {:?}, not a function", exp.ty()));
        }
    }
    Ok(())
}

Type guard

fn is_func_export(ty: &ExternType) -> bool { matches!(ty, ExternType::Func(_)) }

Prevention

When it happens

Trigger: Instantiating a module that exports `__call_view_anon__` as a non-function item (global/memory/table); reached in get_call_view_anon during publish or module host startup.

Common situations: Accidental export name collision with the reserved dunder name in module code or WAT; tooling that exports globals with mangled names colliding after a rename; forks that renamed anonymous view entries.

Related errors


AI-assisted analysis of clockworklabs/SpacetimeDB@6dee26c6ef (2026-08-20). Data as JSON: /api/errors/f16515766046c502. Report an issue: GitHub.