{"record":{"id":"a3bc8615f2a84c12","repo":"sinelaw/fresh","slug":"invalid-plugin-filename","errorCode":null,"errorMessage":"Invalid plugin filename","messagePattern":"Invalid plugin filename","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/fresh-plugin-runtime/src/thread.rs","lineNumber":1429,"sourceCode":"    /// `.d.ts` emit for the plugin source, produced by oxc's\n    /// isolated-declarations transformer. Present on every successful\n    /// TS/JS prepare; callers can use it to assemble a consolidated\n    /// plugins.d.ts so init.ts/other plugins can reach each plugin's\n    /// public types without manual `as`-casts. `None` only when\n    /// isolated-declarations emit failed outright — the plugin still\n    /// loads at runtime.\n    declarations: Option<String>,\n}\n\n/// Prepare a plugin for execution: read source, transpile, extract dependencies.\n///\n/// This function does I/O and CPU-bound work only — no QuickJS interaction.\n/// It is safe to call from any thread (all inputs/outputs are Send).\nfn prepare_plugin(path: &Path) -> Result<PreparedPlugin> {\n    let plugin_name = path\n        .file_stem()\n        .and_then(|s| s.to_str())\n        .ok_or_else(|| anyhow!(\"Invalid plugin filename\"))?\n        .to_string();\n\n    let source = std::fs::read_to_string(path)\n        .map_err(|e| anyhow!(\"Failed to read plugin {}: {}\", path.display(), e))?;\n\n    let filename = path\n        .file_name()\n        .and_then(|s| s.to_str())\n        .unwrap_or(\"plugin.ts\");\n\n    // Extract dependencies before transpilation\n    let dependencies = fresh_parser_js::extract_plugin_dependencies(&source);\n\n    // Emit `.d.ts` via oxc's isolated-declarations before the\n    // transpile step consumes `source`. We want the raw TS (every\n    // `export type`, `export interface`, and `declare global` block\n    // the plugin author wrote) so downstream plugins and init.ts\n    // reach the plugin's public types without casts. Failures are","sourceCodeStart":1411,"sourceCodeEnd":1447,"githubUrl":"https://github.com/sinelaw/fresh/blob/67894ca5463dbd7a89bb31add4627c27d6b79d83/crates/fresh-plugin-runtime/src/thread.rs#L1411-L1447","documentation":"prepare_plugin rejects a plugin path whose final path component has no valid UTF-8 file stem (path.file_stem() returns None or the stem is not valid UTF-8). This fires during plugin preparation when the discovered plugin file has a non-UTF-8 or missing stem (e.g. an odd raw-bytes filename); preparation aborts instead of producing a PreparedPlugin.","triggerScenarios":"Thrown at crates/fresh-plugin-runtime/src/thread.rs:1429 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":["Rename the plugin file so its stem is valid UTF-8 plain ASCII (e.g. my-plugin.ts).","Remove or fix the offending file in the plugins directory and rescan/reload plugins.","If the file came from an archive or copy tool, re-extract/copy with a UTF-8-capable locale so the filename round-trips correctly.","Check the plugin discovery path configuration for stray malformed filenames."],"exampleFix":null,"handlingStrategy":"validation","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"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"}