{"record":{"id":"b41f0026d84b4ff5","repo":"sinelaw/fresh","slug":"js-error-in-stack-trace","errorCode":null,"errorMessage":"JS error in {}: {}: {}\nStack trace:\n{}","messagePattern":"JS error in (.+?): (.+?): (.+?)\nStack trace:\n(.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/fresh-plugin-runtime/src/backend/quickjs_backend.rs","lineNumber":412,"sourceCode":"    source_name: &str,\n) -> anyhow::Error {\n    // Check if this is an exception that we can catch for more details\n    if err.is_exception() {\n        // Try to catch the exception to get the full error object\n        let exc = ctx.catch();\n        if !exc.is_undefined() && !exc.is_null() {\n            // Try to get error message and stack from the exception object\n            if let Some(exc_obj) = exc.as_object() {\n                let message: String = exc_obj\n                    .get::<_, String>(\"message\")\n                    .unwrap_or_else(|_| \"Unknown error\".to_string());\n                let stack: String = exc_obj.get::<_, String>(\"stack\").unwrap_or_default();\n                let name: String = exc_obj\n                    .get::<_, String>(\"name\")\n                    .unwrap_or_else(|_| \"Error\".to_string());\n\n                if !stack.is_empty() {\n                    return anyhow::anyhow!(\n                        \"JS error in {}: {}: {}\\nStack trace:\\n{}\",\n                        source_name,\n                        name,\n                        message,\n                        stack\n                    );\n                } else {\n                    return anyhow::anyhow!(\"JS error in {}: {}: {}\", source_name, name, message);\n                }\n            } else {\n                // Exception is not an object, try to convert to string\n                let exc_str: String = exc\n                    .as_string()\n                    .and_then(|s: &rquickjs::String| s.to_string().ok())\n                    .unwrap_or_else(|| format!(\"{:?}\", exc));\n                return anyhow::anyhow!(\"JS error in {}: {}\", source_name, exc_str);\n            }\n        }","sourceCodeStart":394,"sourceCodeEnd":430,"githubUrl":"https://github.com/sinelaw/fresh/blob/67894ca5463dbd7a89bb31add4627c27d6b79d83/crates/fresh-plugin-runtime/src/backend/quickjs_backend.rs#L394-L430","documentation":"format_js_error converts a caught rquickjs exception into a Rust anyhow error. When the exception object exposes a non-empty 'stack' property, the error includes the source name, the JS error name and message, and the full JS stack trace.","triggerScenarios":"Plugin JavaScript code throws or has an uncaught exception (TypeError, ReferenceError, user-thrown Error) during execute_js; the exception is captured via the promise rejection tracker or eval and formatted with its stack.","commonSituations":"Calling an undefined function or property in a plugin; bad arguments to the plugin API; an async plugin callback rejecting; a typo introduced in plugin code after an update.","solutions":["Read the stack trace in the error to locate the throwing JS line in your plugin","Fix the offending JS (undefined function/property, bad arguments, etc.)","Wrap risky plugin code in try/catch and reject promises explicitly","Re-run with the updated plugin and confirm the error is gone"],"exampleFix":"// before (plugin.js)\nconst cfg = config.settings.timeout; // settings is undefined\n// after\nconst cfg = config.settings?.timeout ?? 3000;","handlingStrategy":"try-catch","validationCode":"// before executing a plugin, lint it for obvious ReferenceErrors/TypeErrors\nnpx eslint --no-eslintrc --env browser plugin.js","typeGuard":null,"tryCatchPattern":"match backend.execute_js(src) {\n    Ok(v) => v,\n    Err(e) if e.to_string().contains(\"JS error in\") => {\n        tracing::error!(\"plugin failed: {e:#}\");\n        // disable plugin or fall back\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["Run plugin code through a linter before loading","Use TypeScript for plugins to catch undefined members at compile time","Add try/catch around plugin entry points","Test plugins in isolation before enabling in production"],"tags":["javascript","quickjs","stack-trace"],"backgroundTag":"unexpected-response-shape","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"}