wasmerio/wasmer · error
Cannot write non-scalar value as bytes
Error message
Cannot write non-scalar value as bytes
What it means
`write_value` in the `__main__`-style dynamic closure call syscall (`call_dynamic`) serializes `Value`s into linear memory as raw bytes. Only scalar types (i32/i64/f32/f64/v128) have byte representations; ExternRef, FuncRef, and ExceptionRef values cannot be written as byte slices, so the code panics instead of writing garbage.
Source
Thrown at lib/wasix/src/syscalls/wasix/call_dynamic.rs:33
}
}};
}
fn write_value(
memory: &MemoryView,
offset: &mut u64,
max: u64,
strict: bool,
value: &Value,
) -> Result<bool, MemoryAccessError> {
match value {
Value::I32(value) => write_value!(memory, *offset, max, strict, value),
Value::I64(value) => write_value!(memory, *offset, max, strict, value),
Value::F32(value) => write_value!(memory, *offset, max, strict, value),
Value::F64(value) => write_value!(memory, *offset, max, strict, value),
Value::V128(value) => write_value!(memory, *offset, max, strict, value),
// ExternRef, FuncRef, and ExceptionRef cannot be represented as byte slices
_ => panic!("Cannot write non-scalar value as bytes"),
}
}
macro_rules! read_value {
($memory:expr, $offset:expr, $max:expr, $strict:expr, $ty:ident, $val:ident, $len:expr) => {{
if $offset + $len > $max {
Ok(if $strict {
None
} else {
Some(Value::$val($ty::default()))
})
} else {
let mut buffer = [0u8; $len];
$memory.read($offset, &mut buffer)?;
$offset += $len;
Ok(Some(Value::$val($ty::from_le_bytes(buffer))))
}
}};View on GitHub (pinned to 8c4b9ee9d3)
Solutions
- Restrict dynamically called functions to scalar-only signatures (i32/i64/f32/f64/v128) — wrap ref-taking functions with a scalar adapter
- Pass references through a side table (index as i32) instead of embedding them in the dynamic call's memory arguments
- Validate the target function's type against scalar-only types before invoking `call_dynamic`
- If refs are required, use direct (non-dynamic) Wasm invocation through the linker where references are supported
Example fix
// before: dynamic call with a funcref arg args.push(Value::FuncRef(Some(funcref))); write_value(memory, &mut off, max, strict, &Value::FuncRef(...)); // panics // after: pass an index into a side table args.push(Value::I32(funcrev_index as i32)); write_value(memory, &mut off, max, strict, &Value::I32(funcrev_index as i32));
Defensive patterns
Strategy: validation
Validate before calling
// Reject non-scalar argument values before the dynamic call
if !args.iter().all(|v| matches!(v,
Value::I32(_) | Value::I64(_) | Value::F32(_) | Value::F64(_) | Value::V128(_)))
{
return Err(Errno::Notsup);
} Type guard
fn is_scalar_value(v: &Value) -> bool {
matches!(v, Value::I32(_) | Value::I64(_) | Value::F32(_) | Value::F64(_) | Value::V128(_))
} Try / catch
let result = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| write_value(memory, &mut off, max, strict, &value)));
if result.is_err() { /* handle non-scalar arg: use side-table handle instead */ } Prevention
- Only dynamic-call functions with scalar-only signatures
- Pass references as i32 side-table handles
- Validate the callee's type against scalars before call_dynamic
- Keep closure descriptors generated from sanitized function types
When it happens
Trigger: Calling a function via `call_dynamic` (indirect `__indirect_function_table` invocation) whose parameters include a reference type (externref/funcref/exceptionref), with argument values supplied from memory or host code.
Common situations: Dynamically calling WASIX closure functions from modules that use the reference-types proposal; host code building argument buffers for dynamic calls with non-scalar signatures; ABI mismatches where a table slot's function type contains refs but the caller assumes scalars.
Related errors
- Cannot read non-scalar value from memory
- Cannot get size of reference type
- Cannot store reference type
- Failed to free closure index: {e}
- Cannot load reference type
AI-assisted analysis of wasmerio/wasmer@8c4b9ee9d3 (2026-09-01).
Data as JSON: /api/errors/05b7b62d15cca39f.
Report an issue: GitHub.