{"record":{"id":"b9034d00bf60b869","repo":"influxdata/influxdb","slug":"invalid-utf-8-in-parent-directory-path","errorCode":null,"errorMessage":"Invalid UTF-8 in parent directory path","messagePattern":"Invalid UTF-8 in parent directory path","errorType":"error_code","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"influxdb3_py_api/src/system_py.rs","lineNumber":340,"sourceCode":"    py: Python<'py>,\n    plugin_root: &Path,\n    function_name: &str,\n    missing_fn_error: ExecutePluginError,\n) -> Result<Bound<'py, PyAny>, ExecutePluginError> {\n    let parent_dir = plugin_root\n        .parent()\n        .ok_or_else(|| anyhow!(\"Plugin root has no parent directory\"))?;\n    let module_name = plugin_root\n        .file_name()\n        .and_then(|n| n.to_str())\n        .ok_or_else(|| anyhow!(\"Invalid plugin directory name\"))?;\n\n    let sys = py.import(\"sys\").map_err(anyhow::Error::from)?;\n    let sys_path = sys.getattr(\"path\").map_err(anyhow::Error::from)?;\n\n    let parent_dir_str = parent_dir\n        .to_str()\n        .ok_or_else(|| anyhow!(\"Invalid UTF-8 in parent directory path\"))?;\n\n    // Acquire while attached to the Python runtime; `lock_py_attached` detaches\n    // internally if the lock is contended, avoiding a GIL/lock deadlock.\n    let _sys_path_guard = SYS_PATH_LOCK.lock_py_attached(py);\n\n    // Add parent directory to sys.path\n    sys_path\n        .call_method1(\"insert\", (0, parent_dir_str))\n        .map_err(anyhow::Error::from)?;\n\n    // A plugin dir added after FileFinder cached the parent is invisible until\n    // import caches are invalidated; retry once.\n    let import_result = match py.import(module_name) {\n        Err(e) if is_module_not_found(py, &e, module_name) => {\n            let _ = py\n                .import(\"importlib\")\n                .and_then(|m| m.call_method0(\"invalidate_caches\"));\n            py.import(module_name)","sourceCodeStart":322,"sourceCodeEnd":358,"githubUrl":"https://github.com/influxdata/influxdb/blob/06200ef96ba82c5f6727e5038a83af8e722c6875/influxdb3_py_api/src/system_py.rs#L322-L358","documentation":"Thrown by load_function_from_module when the parent directory of the plugin root (the directory that must be prepended to sys.path so the plugin module is importable) is not valid UTF-8. Python's sys.path entries must be strings, so a non-UTF-8 OsStr cannot be converted with to_str().","triggerScenarios":"load_plugin_function invoked with a plugin_directory whose PARENT path component contains non-UTF-8 bytes (e.g. a directory name with raw bytes or invalid encoding), preventing `parent_dir.to_str()` from succeeding.","commonSituations":"InfluxDB installed or plugins stored under a path containing characters produced by a non-UTF-8 filesystem encoding or pasted control characters; running under a locale like LC_ALL=C/POSIX where user-created paths use surrogate bytes; symlinks or mounts with unusual names.","solutions":["Rename the offending ancestor directory of the plugin path so the entire path is valid UTF-8.","Check the filesystem encoding/locale the process runs under (`locale`); run with a UTF-8 locale (LC_ALL=C.UTF-8) so paths encode cleanly.","Validate the plugin directory path with `Path::to_str().is_some()` before calling the API and fail fast with a clear message.","Avoid symlinking plugin dirs through paths with exotic names; place plugins under a simple ASCII path like /var/lib/influxdb3/plugins."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"const path = process.env.INFLUXDB3_PLUGIN_DIR ?? \"\";\nconst encoder = new TextEncoder();\n// Node keeps UTF-8 internally; validate round-trip of raw bytes from the FS before use\nif (!path || Buffer.compare(Buffer.from(path, \"utf8\"), encoder.encode(path)) !== 0) {\n  throw new Error(`Plugin dir path '${path}' is not valid UTF-8`);\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Run the server under a UTF-8 locale (LC_ALL=C.UTF-8).","Keep the whole plugin path (including ancestors) ASCII/UTF-8; avoid renamed dirs with exotic bytes.","Validate with Rust's Path::to_str() before calling the API and surface a clear config error."],"tags":["python-plugins","filesystem","path","utf-8"],"backgroundTag":"invalid-env-var-value","analyzedSha":"06200ef96ba82c5f6727e5038a83af8e722c6875","analyzedAt":"2026-09-19T12:55:30.003Z","contentChangedAt":"2026-09-19T12:55:30.003Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}