sinelaw/fresh · critical

Failed to create QuickJS runtime

Error message

Failed to create QuickJS runtime: {}

What it means

Constructor failure of the QuickJS backend: rquickjs's Runtime::new() failed, meaning the underlying QuickJS engine could not be initialized (typically allocation/limit setup failure or memory pressure in the embedded engine). No plugin can run in this process state, so with_state_responses_and_resources propagates the wrapped engine error to the plugin thread instead of returning a backend instance.

Solutions

  1. Check memory limits (ulimit -v, container memory caps) and raise them
  2. Verify the build includes a working rquickjs/QuickJS native library for the platform
  3. Reduce concurrent backend instances
  4. Capture and inspect the wrapped inner error for the root cause

Example fix

// before
docker run -m 32m my-host   # too small for QuickJS init
// after
docker run -m 512m my-host
Defensive patterns

Strategy: try-catch

Validate before calling

// check available memory before initializing the backend
let mem = mem_info();
if mem.available < 256 * 1024 * 1024 { return Err("insufficient memory for plugin backend"); }

Try / catch

match QuickJsBackend::new(sender, handles, handlers) {
    Ok(b) => b,
    Err(e) if e.to_string().contains("Failed to create QuickJS runtime") => {
        eprintln!("cannot start plugin engine: {e:#}");
        run_without_plugins()
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Runtime::new() returns an error — typically resource exhaustion (cannot allocate/initialize the QuickJS engine), unsupported platform build, or repeated runtime creation hitting OS limits (threads/memory).

Common situations: Embedded hosts running in memory-constrained containers; low ulimit environments; broken or mismatched rquickjs native build; platform without required QuickJS support.

Related errors


AI-assisted analysis of sinelaw/fresh@67894ca546 (2026-09-13). Data as JSON: /api/errors/674a0948d0113eb9. Report an issue: GitHub.

Appendix: source

Thrown at crates/fresh-plugin-runtime/src/backend/quickjs_backend.rs:8890

            event_handlers,
        )
    }

    /// Create a new QuickJS backend with editor state, shared pending responses,
    /// and a shared async resource owner map
    pub fn with_state_responses_and_resources(
        state_snapshot: Arc<RwLock<EditorStateSnapshot>>,
        command_sender: mpsc::Sender<PluginCommand>,
        pending_responses: PendingResponses,
        services: Arc<dyn fresh_core::services::PluginServiceBridge>,
        async_resource_owners: AsyncResourceOwners,
        search_handles: SearchHandleRegistry,
        event_handlers: EventHandlerRegistry,
    ) -> Result<Self> {
        tracing::debug!("QuickJsBackend::new: creating QuickJS runtime");

        let runtime =
            Runtime::new().map_err(|e| anyhow!("Failed to create QuickJS runtime: {}", e))?;

        // Set up promise rejection tracker to catch unhandled rejections
        let rejection_sender = command_sender.clone();
        runtime.set_host_promise_rejection_tracker(Some(Box::new(
            move |ctx, _promise, reason, is_handled| {
                if !is_handled {
                    // Format the rejection reason
                    let error_msg = if let Some(exc) = reason.as_exception() {
                        format!(
                            "{}: {}",
                            exc.message().unwrap_or_default(),
                            exc.stack().unwrap_or_default()
                        )
                    } else {
                        format!("{:?}", reason)
                    };

                    tracing::error!("Unhandled Promise rejection: {}", error_msg);

View on GitHub (pinned to 67894ca546)