ruvnet/RuView · error

plugin `{id}` setup returned failure code {result}

Error message

plugin `{id}` setup returned failure code {result}

What it means

Anyhow bail during WASM plugin loading: the module loaded and its exported setup was invoked (call_setup with a bootstrap ConfigEntryJson), but the guest returned a non-zero exit code. The host reacts by calling the plugin's teardown, running teardown_wasm over already-loaded plugins, and aborting server startup with the plugin id and the exact failure code.

Source

Thrown at v2/crates/homecore-server/src/plugins.rs:217

    let mut loaded: Vec<(PluginId, WasmPlugin)> = Vec::with_capacity(discovered.len());
    for package in discovered {
        let id = PluginId::new(&package.manifest.domain);
        let bytes = package
            .read_module(config.limits)
            .with_context(|| format!("failed reading plugin `{id}`"))?;
        let plugin = runtime
            .load_plugin(&package.manifest, &bytes, hc.clone(), &policy)
            .with_context(|| format!("plugin `{id}` rejected before setup"))?;
        let config_entry = serde_json::to_string(&ConfigEntryJson::bootstrap(id.as_str()))?;
        let setup_plugin = plugin.clone();
        let result = tokio::task::spawn_blocking(move || setup_plugin.call_setup(&config_entry))
            .await
            .with_context(|| format!("plugin `{id}` setup task failed"))?
            .with_context(|| format!("plugin `{id}` setup trapped"))?;
        if result != 0 {
            let _ = plugin.call_teardown();
            teardown_wasm(loaded).await;
            anyhow::bail!("plugin `{id}` setup returned failure code {result}");
        }
        info!(
            plugin = %id,
            package = %package.package_dir.display(),
            "signed WASM plugin loaded"
        );
        loaded.push((id, plugin));
    }
    Ok(loaded)
}

#[cfg(feature = "wasmtime")]
async fn teardown_wasm(plugins: Vec<(PluginId, WasmPlugin)>) {
    for (_, plugin) in plugins.into_iter().rev() {
        let _ = tokio::task::spawn_blocking(move || plugin.call_teardown()).await;
    }
}

View on GitHub (pinned to 4685618388)

Solutions

  1. Check the plugin's own logs/stdout around setup -- the non-zero code is its failure reason
  2. Rebuild the plugin against the same homecore-plugins/host version as the server so manifest and ABI match
  3. Provide the configuration the plugin's setup expects (its bootstrap config entry) before it is loaded
  4. To get the server up, temporarily move the failing plugin's directory out of the configured plugin dir, fix it, then restore

Example fix

# before
ls /etc/homecore/plugins/
# broken-integration/  (setup returns 3 on missing config)
./homecore-server --plugin-dir /etc/homecore/plugins
# error: plugin `broken-integration` setup returned failure code 3

# after
mv /etc/homecore/plugins/broken-integration /tmp/quarantine/
./homecore-server   # starts with remaining plugins
# fix broken-integration setup/config, rebuild the .wasm, move it back
Defensive patterns

Strategy: try-catch

Validate before calling

// preflight (deploy script): validate each plugin package loads+setups before server start
// run `homecore-server --plugin-dir <dir> --dry-run-plugins` if available, or load in a scratch
// harness first; only promote plugins whose setup exits 0 into the production plugin dir

Try / catch

match load_wasm_plugins(&hc, &config).await {
    Ok(plugins) => plugins,
    Err(e) if e.to_string().contains("setup returned failure code") => {
        tracing::error!("plugin failed setup; quarantining: {e}");
        quarantine_last_plugin(&config)?; // move dir aside, continue boot without it
        load_wasm_plugins(&hc, &config).await?
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: A plugin whose setup() rejects its bootstrap config (missing required config entry, invalid values), a plugin built against a different host ABI/manifest version than this homecore-server, or a guest bug (panic trapped into a failure return). The code in {result} is the plugin's own failure reason.

Common situations: Plugins compiled from an older/newer homecore-plugins SDK than the host; required per-plugin configuration not provided before first start; plugin expects capabilities (FS, network) the policy denies; corrupted .wasm artifact.

Related errors


AI-assisted analysis of ruvnet/RuView@4685618388 (2026-08-16). Data as JSON: /api/errors/bba3c3ddb70f976f. Report an issue: GitHub.