{"record":{"id":"6f13943322f48971","repo":"Zackriya-Solutions/meetily","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":"frontend/src-tauri/src/audio/audio_processing.rs","lineNumber":649,"sourceCode":"    // Create meeting folder if meeting name is provided\n    let final_output_path = if let Some(name) = meeting_name {\n        let sanitized_meeting_name = sanitize_filename(name);\n        let meeting_folder = output_path.join(&sanitized_meeting_name);\n\n        // Create the meeting folder if it doesn't exist\n        if !meeting_folder.exists() {\n            std::fs::create_dir_all(&meeting_folder)?;\n        }\n\n        meeting_folder\n    } else {\n        output_path.clone()\n    };\n\n    let file_path = final_output_path\n        .join(format!(\"{}_{}.mp4\", sanitized_device_name, timestamp))\n        .to_str()\n        .expect(\"Failed to create valid path\")\n        .to_string();\n    let file_path_clone = file_path.clone();\n    // Run FFmpeg in a separate task\n    if !skip_encoding {\n        encode_single_audio(\n            bytemuck::cast_slice(audio),\n            sample_rate,\n            1,\n            &file_path.into(),\n        )?;\n    }\n    Ok(file_path_clone)\n}\n\n/// Write transcript text to a file alongside the recording (legacy plain text format)\npub fn write_transcript_to_file(\n    transcript_text: &str,\n    output_path: &PathBuf,","sourceCodeStart":631,"sourceCodeEnd":667,"githubUrl":"https://github.com/Zackriya-Solutions/meetily/blob/0281737d87d26352fb0adc78c8c0975f691b23d1/frontend/src-tauri/src/audio/audio_processing.rs#L631-L667","documentation":"Path::to_str() returns Option<&str> that is None when the path contains bytes that are not valid UTF-8. The code joins \"{device}_{timestamp}.mp4\" onto the output/meeting folder path and .expect()s, so any non-UTF-8 component in output_path, meeting_folder, or the device name panics the save-recording path.","triggerScenarios":"Output directory or meeting name containing non-UTF-8 bytes (filenames on exFAT/NTFS mounts created by other OSes), Windows paths with unpaired UTF-16 surrogates in device/folder names, or an OS-reported audio device name that is not valid UTF-8.","commonSituations":"Recordings saved to external drives with odd filenames, Bluetooth/virtual audio devices exposing vendor-encoded names, imported audio whose filename flows into the output path, localized OS locales with partial filename decoding.","solutions":["Replace .to_str().expect(...) with .to_string_lossy().to_string() (replacement chars are acceptable for an output filename)","Better: keep the PathBuf and pass &path into encode_single_audio, letting FFmpeg take the OsStr directly","Propagate an anyhow error instead of expect so a bad path degrades to a user-visible message, not a panic","Sanitize the device name to ASCII early (the sanitized_ prefix suggests this was intended)"],"exampleFix":"// before\nlet file_path = final_output_path\n    .join(format!(\"{}_{}.mp4\", sanitized_device_name, timestamp))\n    .to_str()\n    .expect(\"Failed to create valid path\")\n    .to_string();\n\n// after\nlet file_path = final_output_path\n    .join(format!(\"{}_{}.mp4\", sanitized_device_name, timestamp))\n    .to_string_lossy()\n    .to_string();","handlingStrategy":"validation","validationCode":"let joined = final_output_path.join(file_name);\nif joined.to_str().is_none() {\n    log::warn!(\"non-UTF-8 output path; lossy-encoding\");\n}\nlet file_path = joined.to_string_lossy().to_string();","typeGuard":"fn is_utf8_path(p: &std::path::Path) -> bool {\n    p.to_str().is_some()\n}","tryCatchPattern":null,"preventionTips":["Sanitize device and meeting names to ASCII before they enter file paths","Prefer passing PathBuf/&Path to subprocess APIs instead of String","Never .expect() on to_str(); use to_string_lossy or propagate an error"],"tags":["rust","path-handling","utf-8","ffmpeg","audio-save"],"backgroundTag":"non-utf8-file-path","analyzedSha":"0281737d87d26352fb0adc78c8c0975f691b23d1","analyzedAt":"2026-08-16T20:57:52.567Z","schemaVersion":2},"datasetVersion":"2026-08-16T23:17:17.608Z"}