Zackriya-Solutions/meetily · error

Failed to create valid path

Error message

Failed to create valid path

What it means

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.

Source

Thrown at frontend/src-tauri/src/audio/audio_processing.rs:649

    // Create meeting folder if meeting name is provided
    let final_output_path = if let Some(name) = meeting_name {
        let sanitized_meeting_name = sanitize_filename(name);
        let meeting_folder = output_path.join(&sanitized_meeting_name);

        // Create the meeting folder if it doesn't exist
        if !meeting_folder.exists() {
            std::fs::create_dir_all(&meeting_folder)?;
        }

        meeting_folder
    } else {
        output_path.clone()
    };

    let file_path = final_output_path
        .join(format!("{}_{}.mp4", sanitized_device_name, timestamp))
        .to_str()
        .expect("Failed to create valid path")
        .to_string();
    let file_path_clone = file_path.clone();
    // Run FFmpeg in a separate task
    if !skip_encoding {
        encode_single_audio(
            bytemuck::cast_slice(audio),
            sample_rate,
            1,
            &file_path.into(),
        )?;
    }
    Ok(file_path_clone)
}

/// Write transcript text to a file alongside the recording (legacy plain text format)
pub fn write_transcript_to_file(
    transcript_text: &str,
    output_path: &PathBuf,

View on GitHub (pinned to 0281737d87)

Solutions

  1. Replace .to_str().expect(...) with .to_string_lossy().to_string() (replacement chars are acceptable for an output filename)
  2. Better: keep the PathBuf and pass &path into encode_single_audio, letting FFmpeg take the OsStr directly
  3. Propagate an anyhow error instead of expect so a bad path degrades to a user-visible message, not a panic
  4. Sanitize the device name to ASCII early (the sanitized_ prefix suggests this was intended)

Example fix

// before
let file_path = final_output_path
    .join(format!("{}_{}.mp4", sanitized_device_name, timestamp))
    .to_str()
    .expect("Failed to create valid path")
    .to_string();

// after
let file_path = final_output_path
    .join(format!("{}_{}.mp4", sanitized_device_name, timestamp))
    .to_string_lossy()
    .to_string();
Defensive patterns

Strategy: validation

Validate before calling

let joined = final_output_path.join(file_name);
if joined.to_str().is_none() {
    log::warn!("non-UTF-8 output path; lossy-encoding");
}
let file_path = joined.to_string_lossy().to_string();

Type guard

fn is_utf8_path(p: &std::path::Path) -> bool {
    p.to_str().is_some()
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of Zackriya-Solutions/meetily@0281737d87 (2026-08-16). Data as JSON: /api/errors/6f13943322f48971. Report an issue: GitHub.