wasmerio/wasmer · error · anyhow::Error
env.memory import for Wasm C API module is not a memory
Error message
env.memory import for Wasm C API module is not a memory
What it means
When the Wasm C API module requires an imported memory `env.memory`, register_imports checks whether the module instance already exports something under ("env","memory"). If that export exists but is not an Extern::Memory, the type contract is violated and it bails instead of coercing. The C API state needs a real Memory handle to operate.
Source
Thrown at lib/c-api-imports/src/lib.rs:155
self.validate_supported()?;
if self.version.is_none() {
return Ok(());
}
let func_env = FunctionEnv::new(
&mut *store,
WasmCapiEnv {
resolve_module_sync: self.resolve_module_sync.clone(),
..WasmCapiEnv::default()
},
);
self.func_env = Some(func_env.clone());
register_wasm_c_api_imports(store, &func_env, io);
if let Some(memory_type) = self.imported_memory_type {
if let Some(existing) = io.get_export("env", "memory") {
let Extern::Memory(memory) = existing else {
bail!("env.memory import for Wasm C API module is not a memory");
};
self.set_memory(store, &memory)?;
} else {
let memory = Memory::new(&mut *store, memory_type)?;
io.define("env", "memory", memory.clone());
self.set_memory(store, &memory)?;
}
}
if let Some(table_type) = self.imported_table_type {
if let Some(existing) = io.get_export("env", "__indirect_function_table") {
let Extern::Table(table) = existing else {
bail!(
"env.__indirect_function_table import for Wasm C API module is not a table"
);
};
self.set_table(store, &table)?;
} else {View on GitHub (pinned to 8c4b9ee9d3)
Solutions
- Ensure the "env" "memory" export in the Imports object is an actual Memory instance
- Rename/remove the conflicting non-memory export registered under ("env","memory")
- Let Wasmer create the memory by not pre-defining env.memory (it will allocate Memory::new with the module's declared type)
Example fix
// before
io.define("env", "memory", host_func.clone()); // function, not memory
// after
let mem = Memory::new(&mut store, memory_type)?;
io.define("env", "memory", mem); Defensive patterns
Strategy: validation
Validate before calling
if let Some(Extern::Memory(_)) = io.get_export("env", "memory") { /* ok */ } else if io.get_export("env", "memory").is_some() {
return Err("env.memory is defined but not a Memory");
} Type guard
fn is_memory_export(e: Option<&Extern>) -> bool {
matches!(e, Some(Extern::Memory(_)))
} Try / catch
match result {
Err(e) if e.to_string().contains("is not a memory") => fix_env_memory_import_and_retry(),
other => other?,
} Prevention
- Never define env.memory as anything but a Memory in your Imports set
- Reserve the env.memory name for the memory import when using C API modules
- Audit shared import sets for name collisions before add_imports
When it happens
Trigger: Instantiating a module with an `env.memory` import while the imports object already defines "env.memory" as a function/table/global (anything but a Memory), then calling add_imports.
Common situations: Name collision: a host function registered as env.memory; a stale/wrong import defined earlier in the same Imports set; mixing two modules' import sets where one's memory name matches the other's export of a different kind.
Related errors
- env.__indirect_function_table import for Wasm C API module i
- unsupported Wasm C API import version: {version:?}
- unimplemented operator {operator:?}
- cloning JavaScript shared memory should not fail
- `wasm_valtype_kind: argument is a null pointer
AI-assisted analysis of wasmerio/wasmer@8c4b9ee9d3 (2026-09-01).
Data as JSON: /api/errors/db9869d68cba2cde.
Report an issue: GitHub.