wasmerio/wasmer · error · anyhow::Error

Headless is not a valid runtime to instantiate directly

Error message

Headless is not a valid runtime to instantiate directly

What it means

Wasmer's Backend enum includes a Headless variant, but it is only an internal marker (a runtime without a compiler/JS host is not usable as a directly chosen engine). get_engine refuses to instantiate it and bails with this message. The library throws it to prevent users from selecting a pseudo-backend that has no concrete engine implementation.

Source

Thrown at lib/cli/src/backend.rs:721

                if let Some(p) = &runtime_opts.profiler {
                    match p {
                        Profiler::Perfmap => config.enable_perfmap(),
                        Profiler::Gdb => config.enable_debugger(Debugger::Gdb),
                        Profiler::Lldb => config.enable_debugger(Debugger::Lldb),
                    }
                }

                let engine = wasmer_compiler::EngineBuilder::new(config)
                    .set_features(Some(supported_features))
                    .set_target(Some(target.clone()))
                    .engine()
                    .into();
                Ok(engine)
            }
            #[cfg(feature = "v8")]
            Self::V8 => Ok(wasmer::v8::V8::new().into()),
            Self::Headless => bail!("Headless is not a valid runtime to instantiate directly"),
            #[allow(unreachable_patterns)]
            _ => bail!("Unsupported backend type"),
        }
    }

    /// Check if this backend supports all the required WebAssembly features
    #[allow(unreachable_code)]
    pub fn supports_features(&self, required_features: &Features, target: &Target) -> bool {
        // Map BackendType to the corresponding wasmer::BackendKind
        let backend_kind = match self {
            #[cfg(feature = "singlepass")]
            Self::Singlepass => wasmer::BackendKind::Singlepass,
            #[cfg(feature = "cranelift")]
            Self::Cranelift => wasmer::BackendKind::Cranelift,
            #[cfg(feature = "llvm")]
            Self::LLVM => wasmer::BackendKind::LLVM,
            #[cfg(feature = "v8")]
            Self::V8 => wasmer::BackendKind::V8,

View on GitHub (pinned to 8c4b9ee9d3)

Solutions

  1. Choose a concrete backend such as cranelift, llvm, singlepass, or v8 instead of headless.
  2. If you need a compiler-less engine, use the dedicated headless engine API (e.g. wasmer::Engine::headless()) rather than Backend::Headless.get_engine().
  3. Check how the backend is being parsed/configured and fix the invalid value.

Example fix

// before
let engine = Backend::Headless.get_engine()?;
// after
let engine = Backend::Cranelift.get_engine()?;
Defensive patterns

Strategy: validation

Validate before calling

fn ensure_concrete_backend(b: &Backend) -> Result<(), String> {
    match b {
        Backend::Headless => Err("Headless is not a valid runtime to instantiate directly".into()),
        _ => Ok(()),
    }
}

Type guard

fn is_instantiable(b: &Backend) -> bool {
    !matches!(b, Backend::Headless)
}

Try / catch

match backend.get_engine() {
    Ok(engine) => engine,
    Err(e) if e.to_string().contains("Headless is not a valid runtime") => {
        // fall back to a concrete backend
        Backend::Cranelift.get_engine()?
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Calling Backend::Headless.get_engine() (the public helper) while the Headless variant of wasmer::Backend is selected.

Common situations: Passing 'headless' or 'js' as the backend/engine in CLI flags or config (e.g. --backend headless), or programmatically constructing Backend::Headless and then requesting an engine from it.

Related errors


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