wasmerio/wasmer · error

Cannot get size of reference type

Error message

Cannot get size of reference type

What it means

`size` on the closure parameter/result value wrapper returns the in-memory byte width of a value so `closure_prepare` can lay out the call frame. Reference types (`Self::Ref(_)`) are explicitly not supported in WASIX closures, and their width is undefined for this ABI, so the code panics with this message.

Source

Thrown at lib/wasix/src/syscalls/wasix/closure_prepare.rs:51

        let wasix_type = WasmValueType::try_from(value).map_err(|_| Errno::Inval)?;
        match wasix_type {
            WasmValueType::I32 => Ok(Self::I32),
            WasmValueType::I64 => Ok(Self::I64),
            WasmValueType::F32 => Ok(Self::F32),
            WasmValueType::F64 => Ok(Self::F64),
            WasmValueType::V128 => Ok(Self::V128),
            _ => Err(Errno::Inval),
        }
    }
    fn size(&self) -> u64 {
        match self {
            Self::I32 => 4,
            Self::I64 => 8,
            Self::F32 => 4,
            Self::F64 => 8,
            Self::V128 => 16,
            // Not supported in closures.
            Self::Ref(_) => panic!("Cannot get size of reference type"),
        }
    }
    fn store(&self, sink: &mut InstructionSink<'_>, offset: u64, memory_index: u32) {
        match self {
            Self::I32 => sink.i32_store(MemArg {
                offset,
                align: 0,
                memory_index,
            }),
            Self::I64 => sink.i64_store(MemArg {
                offset,
                align: 0,
                memory_index,
            }),
            Self::F32 => sink.f32_store(MemArg {
                offset,
                align: 0,
                memory_index,

View on GitHub (pinned to 8c4b9ee9d3)

Solutions

  1. Change the closure's function signature to use only scalar types (i32/i64/f32/f64/v128)
  2. Replace reference arguments with i32 handles into a host or guest side table
  3. Filter or reject ref-typed signatures when building closure descriptors before calling `closure_prepare`
  4. Recompile the guest module with reference-types disabled or with a closure ABI that maps refs to indices

Example fix

// before: closure over (externref) -> i32
let types = vec![ClosureType::Ref(RefType::Extern)];
// after: pass an index instead
let types = vec![ClosureType::I32];
Defensive patterns

Strategy: validation

Validate before calling

// Before closure_prepare, reject ref-typed signatures
if types.iter().any(|t| matches!(t, ClosureType::Ref(_))) {
    return Err("reference types are not supported in closures".into());
}

Type guard

fn closure_sig_is_scalar(types: &[ClosureType]) -> bool {
    types.iter().all(|t| !matches!(t, ClosureType::Ref(_)))
}

Try / catch

let result = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| param.size()));
if result.is_err() { /* ref param detected: remap to an i32 handle and retry */ }

Prevention

When it happens

Trigger: Preparing a dynamic closure (`closure_prepare`) whose signature includes a reference-typed parameter or result (externref/funcref/exceptionref), causing the size computation to hit the `Ref` arm.

Common situations: Guest modules compiled with reference-types enabled declaring closures over ref-taking functions; code generators emitting closure descriptors from raw function types without filtering refs; ABI drift where newer module types include refs the runtime closure path doesn't support.

Related errors


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