{"record":{"id":"113d5136b63ee6af","repo":"sinelaw/fresh","slug":"failed-to-create-quickjs-context-for-plugin","errorCode":null,"errorMessage":"Failed to create QuickJS context for plugin {}: {}","messagePattern":"Failed to create QuickJS context for plugin (.+?): (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/fresh-plugin-runtime/src/backend/quickjs_backend.rs","lineNumber":9117,"sourceCode":"        let plugin_name = Path::new(source_name)\n            .file_stem()\n            .and_then(|s| s.to_str())\n            .unwrap_or(\"unknown\");\n\n        tracing::debug!(\n            \"execute_js: starting for plugin '{}' from '{}'\",\n            plugin_name,\n            source_name\n        );\n\n        // Get or create context for this plugin\n        let context = {\n            let mut contexts = self.plugin_contexts.borrow_mut();\n            if let Some(ctx) = contexts.get(plugin_name) {\n                ctx.clone()\n            } else {\n                let ctx = Context::full(&self.runtime).map_err(|e| {\n                    anyhow!(\n                        \"Failed to create QuickJS context for plugin {}: {}\",\n                        plugin_name,\n                        e\n                    )\n                })?;\n                self.setup_context_api(&ctx, plugin_name)?;\n                contexts.insert(plugin_name.to_string(), ctx.clone());\n                ctx\n            }\n        };\n\n        // Wrap plugin code in IIFE to prevent TDZ errors and scope pollution\n        // This is critical for plugins like vi_mode that declare `const editor = ...`\n        // which shadows the global `editor` causing TDZ if not wrapped.\n        let wrapped_code = format!(\"(function() {{ {} }})();\", code);\n        let wrapped = wrapped_code.as_str();\n\n        context.with(|ctx| {","sourceCodeStart":9099,"sourceCodeEnd":9135,"githubUrl":"https://github.com/sinelaw/fresh/blob/67894ca5463dbd7a89bb31add4627c27d6b79d83/crates/fresh-plugin-runtime/src/backend/quickjs_backend.rs#L9099-L9135","documentation":"When loading a plugin that has no dedicated JS context yet, the backend creates one via Context::full(&self.runtime). Failure aborts the plugin load with this error naming the plugin and wrapping the rquickjs error.","triggerScenarios":"Context allocation fails while lazily initializing a per-plugin context — runtime memory exhaustion, corrupted runtime state, or an rquickjs internal error during plugin load.","commonSituations":"Loading many plugins simultaneously in a memory-limited host; loading a plugin after the runtime entered a bad state (e.g. after OOM); rquickjs native library issues.","solutions":["Check memory limits and reduce the number of concurrently loaded plugins","Retry the plugin load after freeing resources","Inspect the wrapped rquickjs error for the concrete cause","Restart the plugin host/backend if runtime state is corrupted"],"exampleFix":"// before\n// load all 50 plugins at startup under 64MB limit\n// after\n// raise limit and load lazily\ndocker run -m 512m my-host\nfor plugin in needed_plugins { backend.load_module(plugin).await?; }","handlingStrategy":"try-catch","validationCode":"// bound concurrent plugin loads to avoid context-creation pressure\nif active_plugins() >= MAX_PLUGINS { return Err(\"plugin limit reached\"); }","typeGuard":null,"tryCatchPattern":"match backend.load_module(path).await {\n    Err(e) if e.to_string().contains(\"Failed to create QuickJS context for plugin\") => {\n        eprintln!(\"could not init context for plugin: {e:#}\");\n        unload_unused_plugins();\n        retry_once()\n    }\n    other => other,\n}","preventionTips":["Cap the number of simultaneously loaded plugins","Monitor memory before loading additional plugins","Load plugins lazily rather than all at startup","Restart the backend if context creation repeatedly fails"],"tags":["quickjs","context-init","plugin-loading"],"backgroundTag":"module-init-failed","analyzedSha":"67894ca5463dbd7a89bb31add4627c27d6b79d83","analyzedAt":"2026-09-13T15:04:03.701Z","contentChangedAt":"2026-09-13T15:04:03.701Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}