{"record":{"id":"aa1c463c7d2db092","repo":"PyO3/pyo3","slug":"wasi-strings-are-utf8","errorCode":null,"errorMessage":"wasi strings are UTF8","messagePattern":"wasi strings are UTF8","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/conversions/std/osstr.rs","lineNumber":43,"sourceCode":"impl<'py> IntoPyObject<'py> for &OsStr {\n    type Target = PyString;\n    type Output = Bound<'py, Self::Target>;\n    type Error = Infallible;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const OUTPUT_TYPE: PyStaticExpr = PyString::TYPE_HINT;\n\n    fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {\n        // If the string is UTF-8, take the quick and easy shortcut\n        #[cfg(not(target_os = \"wasi\"))]\n        if let Some(valid_utf8_path) = self.to_str() {\n            return valid_utf8_path.into_pyobject(py);\n        }\n\n        #[cfg(target_os = \"wasi\")]\n        {\n            self.to_str()\n                .expect(\"wasi strings are UTF8\")\n                .into_pyobject(py)\n        }\n\n        #[cfg(any(unix, target_os = \"emscripten\"))]\n        {\n            let bytes = self.as_bytes();\n            let ptr = bytes.as_ptr().cast();\n            let len = bytes.len() as ffi::Py_ssize_t;\n            // SAFETY: passing valid pointer to python API\n            unsafe {\n                // DecodeFSDefault automatically chooses an appropriate decoding mechanism to\n                // parse os strings losslessly (i.e. surrogateescape most of the time)\n                Ok(ffi::PyUnicode_DecodeFSDefaultAndSize(ptr, len)\n                    .assume_owned(py)\n                    .cast_into_unchecked())\n            }\n        }\n","sourceCodeStart":25,"sourceCodeEnd":61,"githubUrl":"https://github.com/PyO3/pyo3/blob/ac9b6899d348be4d54614d060dea53a645a12e36/src/conversions/std/osstr.rs#L25-L61","documentation":"Converting an OsStr/Path to Python on the WASI target assumes WASI strings are valid UTF-8, so the code calls to_str().expect(\"wasi strings are UTF8\"). If the underlying bytes are not UTF-8 (e.g. a path built from raw invalid bytes), this panics at runtime during into_pyobject.","triggerScenarios":"Calling into_pyobject (or returning a Path/OsStr from a #[pyfunction]) on WASI where the OsStr contains non-UTF-8 bytes, e.g. OsStr::from_bytes(b\"\\xff\") or a path read from the filesystem with invalid encoding.","commonSituations":"WASI builds handling paths or environment values sourced from raw bytes (host-provided preopen names, argv, or file names read via OsStrExt::from_bytes) that are not UTF-8.","solutions":["Validate the OsStr/Path with to_str() before converting; handle the None case explicitly.","Fall back to lossy conversion via to_string_lossy() if exact bytes are not required.","On non-WASI targets prefer the byte-preserving branch; on WASI reject or sanitize non-UTF-8 paths at the boundary.","Normalize inputs early (e.g. accept String instead of PathBuf) when you control the API."],"exampleFix":"// before\npyo3_path.to_str().expect(\"wasi strings are UTF8\").into_pyobject(py)\n// after\nmatch pyo3_path.to_str() {\n    Some(s) => s.into_pyobject(py),\n    None => return Err(PyValueError::new_err(\"path is not valid UTF-8\")),\n}","handlingStrategy":"validation","validationCode":"// Check UTF-8 validity before converting an OsStr/Path on WASI\nfn is_utf8_path(p: &std::ffi::OsStr) -> bool { p.to_str().is_some() }","typeGuard":"fn as_utf8(p: &std::ffi::OsStr) -> Option<&str> { p.to_str() }","tryCatchPattern":"// Panic cannot be caught idiomatically; instead avoid expect in your own code:\nlet obj = match path.to_str() {\n    Some(s) => s.into_pyobject(py)?,\n    None => return Err(PyValueError::new_err(\"path is not valid UTF-8\")),\n};","preventionTips":["Validate OsStr/Path contents with to_str() before returning them to Python on WASI.","Sanitize raw-byte paths (from preopens, argv, env) at the WASI boundary.","Prefer String/PathBuf constructed from checked UTF-8 sources in WASI builds.","Use to_string_lossy() as a fallback when byte fidelity is not critical."],"tags":["pyo3","wasi","path-conversion","utf8","panic"],"backgroundTag":"non-utf8-path-conversion","analyzedSha":"ac9b6899d348be4d54614d060dea53a645a12e36","analyzedAt":"2026-09-05T09:20:35.319Z","contentChangedAt":"2026-09-05T09:20:35.319Z","schemaVersion":2},"datasetVersion":"2026-09-12T12:17:11.808Z"}