{"record":{"id":"be17cf7f0732264a","repo":"sinelaw/fresh","slug":"failed-to-read-plugin","errorCode":null,"errorMessage":"Failed to read plugin {}: {}","messagePattern":"Failed to read plugin (.+?): (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/fresh-plugin-runtime/src/backend/quickjs_backend.rs","lineNumber":9051,"sourceCode":"                install_console(&ctx, &globals)?;\n                ctx.eval::<(), _>(EDITOR_PROMISE_BOOTSTRAP.as_bytes())?;\n\n                Ok::<_, rquickjs::Error>(())\n            })\n            .map_err(|e| anyhow!(\"Failed to set up global API: {}\", e))?;\n\n        Ok(())\n    }\n\n    /// Load and execute a TypeScript/JavaScript plugin from a file path\n    pub async fn load_module_with_source(\n        &mut self,\n        path: &str,\n        _plugin_source: &str,\n    ) -> Result<()> {\n        let path_buf = PathBuf::from(path);\n        let source = std::fs::read_to_string(&path_buf)\n            .map_err(|e| anyhow!(\"Failed to read plugin {}: {}\", path, e))?;\n\n        let filename = path_buf\n            .file_name()\n            .and_then(|s| s.to_str())\n            .unwrap_or(\"plugin.ts\");\n\n        // Check for ES imports - these need bundling to resolve dependencies\n        if has_es_imports(&source) {\n            // Try to bundle (this also strips imports and exports)\n            match bundle_module(&path_buf) {\n                Ok(bundled) => {\n                    self.execute_js(&bundled, path)?;\n                }\n                Err(e) => {\n                    tracing::warn!(\n                        \"Plugin {} uses ES imports but bundling failed: {}. Skipping.\",\n                        path,\n                        e","sourceCodeStart":9033,"sourceCodeEnd":9069,"githubUrl":"https://github.com/sinelaw/fresh/blob/67894ca5463dbd7a89bb31add4627c27d6b79d83/crates/fresh-plugin-runtime/src/backend/quickjs_backend.rs#L9033-L9069","documentation":"File-read failure while loading a plugin module: std::fs::read_to_string on the plugin path failed in load_module_with_source (file missing, permission denied, path is a directory, or the file is not valid UTF-8). The wrapped io::Error is returned so the plugin host can report which plugin failed and why; no code from that plugin is ever evaluated.","triggerScenarios":"Plugin path does not exist, is a directory, or the process lacks read permission; invalid UTF-8 in the plugin file also fails read_to_string.","commonSituations":"Typoed or relative plugin path from the wrong working directory; plugin file deleted/moved after registration; permission changes on the plugin directory; non-UTF8 plugin files.","solutions":["Verify the plugin path exists and is spelled correctly (use an absolute path)","Check file read permissions for the process user","Ensure the plugin file is valid UTF-8 text","Re-install/re-sync the plugin if it was deleted or moved"],"exampleFix":"// before\nbackend.load_module(\"./plugn.ts\").await?;\n// after\nassert!(std::path::Path::new(\"./plugin.ts\").is_file());\nbackend.load_module(\"./plugin.ts\").await?;","handlingStrategy":"validation","validationCode":"fn plugin_readable(path: &str) -> Result<(), String> {\n    let p = std::path::Path::new(path);\n    if !p.is_file() { return Err(format!(\"{path}: not a file\")); }\n    std::fs::File::open(p).map_err(|e| format!(\"{path}: {e}\"))?.metadata()?;\n    Ok(())\n}","typeGuard":null,"tryCatchPattern":"match backend.load_module(path).await {\n    Err(e) if e.to_string().starts_with(\"Failed to read plugin\") => {\n        eprintln!(\"plugin file problem: {e:#}\");\n        resync_plugin_dir();\n    }\n    other => other,\n}","preventionTips":["Always pass absolute, verified plugin paths","Check file existence and permissions at config load time","Ensure plugin files are UTF-8 text","Re-sync plugin directories after deploys or updates"],"tags":["filesystem","io","plugin-loading"],"backgroundTag":"file-read-failed","analyzedSha":"67894ca5463dbd7a89bb31add4627c27d6b79d83","analyzedAt":"2026-09-13T15:04:03.701Z","contentChangedAt":"2026-09-13T15:04:03.701Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}