sinelaw/fresh · critical

Failed to create QuickJS context

Error message

Failed to create QuickJS context: {}

What it means

Initialization failure of the QuickJS execution Context on top of an already-created runtime: rquickjs's Context::new() (or the immediate global setup that follows) failed. This means the engine runtime exists but no JS context can be fabricated, so the plugin backend cannot evaluate any code; the wrapped error is returned from the backend constructor path and prevents plugin loading entirely.

Solutions

  1. Check memory limits and available RAM
  2. Recreate the backend (drop and rebuild QuickJsBackend)
  3. Check the wrapped rquickjs error for the concrete cause
  4. Update or rebuild rquickjs to match the platform

Example fix

// before
let backend = QuickJsBackend::new(...)?; // after runtime OOM
// after
// free memory / lower concurrency, then:
let backend = QuickJsBackend::new(...).context("plugin backend init")?;
Defensive patterns

Strategy: try-catch

Try / catch

match QuickJsBackend::new(...) {
    Err(e) if e.to_string().contains("Failed to create QuickJS context") => {
        tracing::error!("context init failed: {e:#}");
        retry_after_gc_or_restart_backend()
    }
    other => other,
}

Prevention

When it happens

Trigger: Context::full() fails — engine-level failure while allocating a context on an otherwise-created runtime; usually indicates corrupted runtime state, exhausted memory, or an rquickjs internal error.

Common situations: Memory-pressure environments where the runtime was created but a context cannot be allocated; rquickjs version incompatibilities; constructing many backends rapidly in the same process.

Related errors


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

Appendix: source

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

                            request_id,
                            ok: false,
                            output: None,
                            error: Some(error_msg.clone()),
                        });
                    }

                    if should_panic_on_js_errors() {
                        // Don't panic here - we're inside an FFI callback and rquickjs catches panics.
                        // Instead, set a fatal error flag that the plugin thread loop will check.
                        let full_msg = format!("Unhandled Promise rejection: {}", error_msg);
                        set_fatal_js_error(full_msg);
                    }
                }
            },
        )));

        let main_context = Context::full(&runtime)
            .map_err(|e| anyhow!("Failed to create QuickJS context: {}", e))?;

        let plugin_contexts = Rc::new(RefCell::new(HashMap::new()));
        let registered_actions = Rc::new(RefCell::new(HashMap::new()));
        let next_request_id = Rc::new(RefCell::new(1u64));
        let callback_contexts = Rc::new(RefCell::new(HashMap::new()));
        let plugin_tracked_state = Rc::new(RefCell::new(HashMap::new()));
        let registered_command_names = Rc::new(RefCell::new(HashMap::new()));
        let registered_grammar_languages = Rc::new(RefCell::new(HashMap::new()));
        let registered_language_configs = Rc::new(RefCell::new(HashMap::new()));
        let registered_lsp_servers = Rc::new(RefCell::new(HashMap::new()));
        let plugin_api_exports = Rc::new(RefCell::new(HashMap::new()));

        let backend = Self {
            runtime,
            main_context,
            plugin_contexts,
            event_handlers,
            registered_actions,

View on GitHub (pinned to 67894ca546)