zellij-org/zellij · error
Plugin is not stored in memory
Error message
Plugin is not stored in memory
What it means
Thrown by PluginLoader::load_module_from_memory when a plugin reload expects the already-compiled wasm Module to be parked in the internal plugin_cache keyed by plugin path, but the cache has no entry. The cache is consumed with a one-shot .remove(), so the entry is only present between the first load and the first reload. A miss means the reload path was taken for a plugin that was never cached (or was already reloaded once).
Source
Thrown at zellij-server/src/plugins/plugin_loader.rs:165
self.loading_indication.override_previous_error();
let wasm_bytes = self.plugin_config.resolve_wasm_bytes(&self.plugin_dir)?;
let timer = std::time::Instant::now();
let module = Module::new(&self.engine, &wasm_bytes)?;
log::info!(
"Loaded plugin '{}' in {:?}",
self.plugin_config.path.display(),
timer.elapsed()
);
Ok(module)
}
fn load_module_from_memory(&mut self) -> Result<Module> {
let module = self
.plugin_cache
.lock()
.unwrap()
.remove(&self.plugin_config.path) // TODO: do we still bring it back later?
// maybe we can forgo this dance?
.ok_or(anyhow!("Plugin is not stored in memory"))?;
Ok(module)
}
fn load_plugin_instance(
&mut self,
mut store: Store<PluginEnv>,
instance: &Instance,
) -> Result<()> {
let err_context = || format!("failed to load plugin from instance {instance:#?}");
let main_user_instance = instance.clone();
let start_function = instance
.get_typed_func::<(), ()>(&mut store, "_start")
.with_context(err_context)?;
let load_function = instance
.get_typed_func::<(), ()>(&mut store, "load")
.with_context(err_context)?;
let mut workers = HashMap::new();
for function_name in instance
.exports(&mut store)View on GitHub (pinned to 98a0837077)
Solutions
- Ensure the plugin's first load goes through the code path that inserts the module into plugin_cache (same RunPluginOrAlias path/normalization on both loads) so the reload finds it
- Avoid triggering reload of the same plugin twice; after the first reload the cache entry is gone by design (see the TODO at zellij-server/src/plugins/plugin_loader.rs:167)
- If you control this code, fall back to load_module_from_disk when load_module_from_memory returns None instead of erroring
- Check for concurrent loads of the identical plugin path (e.g. same plugin in tiled and floating panes) and serialize/reuse them
Example fix
// before
let module = self.load_module_from_memory()?;
// after
let module = match self.load_module_from_memory() {
Ok(module) => module,
Err(_) => self.load_module_from_disk()?, // recompile instead of failing
}; Defensive patterns
Strategy: fallback
Validate before calling
// before reloading, ensure a cached module exists for this exact path
let cached = plugin_cache.lock().unwrap().contains_key(&plugin_config.path);
if !cached { plugin_loader.load_module_from_disk()?; } // repopulates path for reload Prevention
- Load each plugin through a single code path so the cache key (canonicalized path) matches between initial load and reload
- Never reload the same plugin path twice without an intervening load; the cache entry is consumed on first use
When it happens
Trigger: Calling start_or_reload on a plugin whose initial load went through load_module_from_disk (never inserted into plugin_cache), reloading the same plugin path twice (the first reload removed the entry), or a cache eviction/race between concurrent loads of the same path.
Common situations: Plugin development with `zellij --layout` hot-reload workflows; two panes loading the same plugin URL causing one to drain the cache; version change altering the cache-insertion path so file-loaded plugins skip caching.
Related errors
- Failed to parse plugin location: {}
- failed to load plugin from disk
- StartOrReloadPlugin missing plugin
- No plugin found at '{}'
- Failed to serialize user configuration: {:?}
AI-assisted analysis of zellij-org/zellij@98a0837077 (2026-08-16).
Data as JSON: /api/errors/90e2028719358148.
Report an issue: GitHub.