wasmerio/wasmer · error · anyhow::Error
The headless engine can't be chosen
Error message
The headless engine can't be chosen
What it means
BackendType::Headless is a placeholder meaning "no compiler, deserialize precompiled artifacts"; it is not a compiler that get_sys_compiler_config can produce a CompilerConfig for. Any attempt to fetch a compiler config for the headless backend bails immediately.
Source
Thrown at lib/cli/src/backend.rs:439
let compiler_config = self.get_sys_compiler_config(backends.first().unwrap())?;
let default_features = compiler_config.default_features_for_target(&target);
let features = self.get_features(&default_features)?;
Ok(wasmer_compiler::EngineBuilder::new(compiler_config)
.set_features(Some(features))
.set_target(Some(target))
.engine()
.into())
}
#[allow(unused_variables)]
#[cfg(feature = "compiler")]
pub(crate) fn get_sys_compiler_config(
&self,
rt: &BackendType,
) -> Result<Box<dyn CompilerConfig>> {
self.validate_profiler()?;
let compiler_config: Box<dyn CompilerConfig> = match rt {
BackendType::Headless => bail!("The headless engine can't be chosen"),
#[cfg(feature = "singlepass")]
BackendType::Singlepass => {
let mut config = wasmer_compiler_singlepass::Singlepass::new();
if self.enable_experimental_unaligned_memory_accesses {
config.allow_experimental_unaligned_memory_accesses(true);
}
if self.enable_verifier {
config.enable_verifier();
}
if self.enable_nan_canonicalization {
config.canonicalize_nans(true);
}
if let Some(p) = &self.profiler {
match p {
Profiler::Perfmap => config.enable_perfmap(),
Profiler::Gdb => config.enable_debugger(Debugger::Gdb),
Profiler::Lldb => config.enable_debugger(Debugger::Lldb),
}View on GitHub (pinned to 8c4b9ee9d3)
Solutions
- Use a compiling backend (cranelift, singlepass, or llvm) instead of headless for compilation paths
- Only use the headless engine with precompiled .wasmu artifacts
- Fix the default backend/engine selection in your configuration or launcher
Example fix
// before let engine = get_engine(&BackendType::Headless, target, &opts)?; // after let engine = get_engine(&BackendType::Cranelift, target, &opts)?;
Defensive patterns
Strategy: validation
Validate before calling
if matches!(rt, BackendType::Headless) {
return Err("headless cannot compile; use cranelift/singlepass/llvm for compilation paths");
} Type guard
fn is_compilable(rt: &BackendType) -> bool {
!matches!(rt, BackendType::Headless | BackendType::V8)
} Try / catch
match result {
Err(e) if e.to_string().contains("headless engine can't be chosen") => {
retry_with_backend(BackendType::Cranelift)
}
other => other?,
} Prevention
- Use Headless only for deserializing precompiled artifacts
- Never set headless as the default engine for run/compile commands
- Map headless requests to a JIT backend in wrapper tooling
When it happens
Trigger: Calling get_sys_compiler_config(rt) with rt == BackendType::Headless, typically via get_sys_compiler_engine_for_target when the chosen engine type is Headless.
Common situations: Passing --engine headless to a command that needs to compile (not just deserialize) a module; programmatically selecting the headless backend where a JIT engine is required; misconfigured runtime defaulting to headless.
Related errors
- The {} backend does not support the required features for th
- The `{compiler}` compiler is not included in this binary.
- Unable to determine the wasmer dir: {e}
- The gdb profiler requires --experimental-artifact
- The lldb profiler requires --experimental-artifact
AI-assisted analysis of wasmerio/wasmer@8c4b9ee9d3 (2026-09-01).
Data as JSON: /api/errors/caf3b35434cff81a.
Report an issue: GitHub.