{"record":{"id":"3757711f30294560","repo":"screenpipe/screenpipe","slug":"failed-to-create-valid-path","errorCode":null,"errorMessage":"Failed to create valid path","messagePattern":"Failed to create valid path","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/screenpipe-audio/src/utils/ffmpeg.rs","lineNumber":156,"sourceCode":"    drop(stdin);\n    debug!(\"Waiting for FFmpeg process to exit\");\n    child\n        .wait_with_output()\n        .map_err(|e| anyhow::anyhow!(\"FFmpeg wait failed: {e}\"))\n}\n\npub fn get_new_file_path_with_timestamp(\n    device: &str,\n    output_path: &PathBuf,\n    capture_time: Option<DateTime<Utc>>,\n) -> String {\n    let ts = capture_time.unwrap_or_else(Utc::now);\n    let new_file_name = ts.format(\"%Y-%m-%d_%H-%M-%S\").to_string();\n    let sanitized_device_name = device.replace(['/', '\\\\'], \"_\");\n    PathBuf::from(output_path)\n        .join(format!(\"{}_{}.mp4\", sanitized_device_name, new_file_name))\n        .to_str()\n        .expect(\"Failed to create valid path\")\n        .to_string()\n}\n\n/// Decode an audio file (MP4/AAC) back to 16kHz mono f32 PCM using ffmpeg.\n/// Returns (samples, sample_rate).\npub fn read_audio_from_file(path: &Path) -> Result<(Vec<f32>, u32)> {\n    let sample_rate: u32 = 16000;\n\n    let ffmpeg_path = find_ffmpeg_path()\n        .ok_or_else(|| anyhow::anyhow!(\"ffmpeg not found in PATH or bundled binaries\"))?;\n    let path_str = path\n        .to_str()\n        .ok_or_else(|| anyhow::anyhow!(\"path is not valid UTF-8: {}\", path.display()))?;\n\n    let mut command = screenpipe_core::ffmpeg_cmd(ffmpeg_path);\n    command\n        .args([\n            \"-i\",","sourceCodeStart":138,"sourceCodeEnd":174,"githubUrl":"https://github.com/screenpipe/screenpipe/blob/4ebf712990fee17eeaf904dacf749b6e96ac9bf3/crates/screenpipe-audio/src/utils/ffmpeg.rs#L138-L174","documentation":"get_new_file_path_with_timestamp builds an output file path as output_path/device_timestamp.mp4 and calls .to_str().expect(\"Failed to create valid path\"). PathBuf::to_str returns None only when the path is not valid UTF-8, so this panics when the output directory or device name contains non-UTF-8 bytes.","triggerScenarios":"output_path configured to a directory with non-UTF-8 bytes (e.g. non-ASCII filesystem encoding) or an audio device whose name contains non-UTF-8 characters that survive sanitization (the sanitizer only replaces '/' and '\\\\').","commonSituations":"devices with emoji/unicode names on odd filesystems; Windows paths with unusual encodings; user-configured output dirs from env vars with invalid bytes.","solutions":["sanitize device names to ASCII/valid-UTF-8 characters instead of only replacing slashes","use .to_string_lossy().into_owned() or propagate an error instead of .expect","validate output_path is valid UTF-8 at configuration load time"],"exampleFix":"// before\n.to_str().expect(\"Failed to create valid path\").to_string()\n// after\n.to_str()\n    .map(str::to_string)\n    .ok_or_else(|| anyhow!(\"output path is not valid UTF-8: {:?}\", output_path))?","handlingStrategy":"validation","validationCode":"fn ensure_utf8_path(p: &Path) -> Result<(), anyhow::Error> {\n    p.to_str().map(|_| ()).ok_or_else(|| anyhow!(\"path {:?} is not valid UTF-8\", p))\n}","typeGuard":"fn is_utf8_path(p: &Path) -> bool { p.to_str().is_some() }","tryCatchPattern":"let path_str = path_buf.to_str()\n    .ok_or_else(|| anyhow!(\"output path not valid UTF-8: {:?}\", path_buf))?;","preventionTips":["sanitize device names to a safe ASCII charset (alnum, dash, underscore), not just slashes","validate configured output directories for UTF-8 validity at startup","prefer to_string_lossy or Result propagation over .expect on to_str"],"tags":["filesystem","path","utf8","panic"],"backgroundTag":"invalid-utf8-path-panic","analyzedSha":"4ebf712990fee17eeaf904dacf749b6e96ac9bf3","analyzedAt":"2026-09-01T23:33:43.065Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-09T06:17:21.866Z"}