{"record":{"id":"2c922d3f4f2d77ad","repo":"Zackriya-Solutions/meetily","slug":"cannot-read-file","errorCode":null,"errorMessage":"Cannot read file: {}","messagePattern":"Cannot read file: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"frontend/src-tauri/src/audio/import.rs","lineNumber":144,"sourceCode":"\n    // Check extension\n    let extension = path\n        .extension()\n        .and_then(|e| e.to_str())\n        .map(|e| e.to_lowercase())\n        .unwrap_or_default();\n\n    if !AUDIO_EXTENSIONS.contains(&extension.as_str()) {\n        return Err(anyhow!(\n            \"Unsupported format: .{}. Supported: {}\",\n            extension,\n            AUDIO_EXTENSIONS.join(\", \")\n        ));\n    }\n\n    // Get file size\n    let metadata = std::fs::metadata(path)\n        .map_err(|e| anyhow!(\"Cannot read file: {}\", e))?;\n    let size_bytes = metadata.len();\n\n    // Check file size limit\n    if size_bytes > MAX_FILE_SIZE_BYTES {\n        return Err(anyhow!(\n            \"File too large: {:.2}GB. Maximum supported size is {}GB\",\n            size_bytes as f64 / (1024.0 * 1024.0 * 1024.0),\n            MAX_FILE_SIZE_BYTES / (1024 * 1024 * 1024)\n        ));\n    }\n\n    // Get filename without extension for title\n    let filename = path\n        .file_stem()\n        .and_then(|s| s.to_str())\n        .unwrap_or(\"Imported Audio\")\n        .to_string();\n","sourceCodeStart":126,"sourceCodeEnd":162,"githubUrl":"https://github.com/Zackriya-Solutions/meetily/blob/0281737d87d26352fb0adc78c8c0975f691b23d1/frontend/src-tauri/src/audio/import.rs#L126-L162","documentation":"validate_audio_file (import.rs:144) wraps the std::fs::metadata error encountered while reading the file's size after the extension gate passed. exists() said true but metadata() failed - the classic TOCTOU window (file vanished between the two syscalls) plus permission and special-file cases. The raw io::Error is embedded, so the suffix distinguishes NotFound, PermissionDenied, and friends.","triggerScenarios":"File deleted or renamed between the exists() check and the metadata() call (sync tools, antivirus quarantine); no read permission (other-user ownership, Windows ACLs, macOS App Sandbox losing the picked path); a special file (/dev node); a network share that dropped; a Windows path exceeding MAX_PATH without long-path enablement.","commonSituations":"Importing from cloud-sync folders (OneDrive/Dropbox placeholder dehydration causes metadata races); corporate folder-redirection with strict ACLs; macOS sandboxed builds losing file access after restart (security-scoped bookmark expired); antivirus locking large media files during scan.","solutions":["Read the io::Error kind in the message: NotFound - re-pick the file; PermissionDenied - fix ownership/ACLs or run outside the sandbox; other kinds - check mount health.","On Windows, grant Read via file Properties > Security; on macOS, re-pick the file in the current session rather than reusing a stored path.","Pause sync tools (or wait for placeholder hydration) before importing.","Retry once after a short delay if the message ends in NotFound - sync tools often release files quickly.","Long term: replace exists()+metadata() with a single metadata() call, mapping NotFound to the friendlier File-does-not-exist message."],"exampleFix":"// before: two syscalls, file can vanish between them\nif !path.exists() { return Err(anyhow!(\"File does not exist: {}\", path.display())); }\nlet metadata = std::fs::metadata(path).map_err(|e| anyhow!(\"Cannot read file: {}\", e))?;\n\n// after: single syscall, classified errors\nlet metadata = match std::fs::metadata(path) {\n    Ok(m) => m,\n    Err(e) if e.kind() == std::io::ErrorKind::NotFound =>\n        return Err(anyhow!(\"File does not exist: {}\", path.display())),\n    Err(e) if e.kind() == std::io::ErrorKind::PermissionDenied =>\n        return Err(anyhow!(\"Permission denied reading: {}\", path.display())),\n    Err(e) => return Err(anyhow!(\"Cannot read file: {}\", e)),\n};","handlingStrategy":"try-catch","validationCode":"// Frontend: prove the folder is readable before invoking validation\nimport { readDir } from '@tauri-apps/plugin-fs';\ntry { await readDir(dirname(path)); } catch { throw new Error('folder unreadable'); }","typeGuard":null,"tryCatchPattern":"// Rust: classify the io::Error kind for the user\nlet metadata = match std::fs::metadata(path) {\n    Ok(m) => m,\n    Err(e) if e.kind() == std::io::ErrorKind::NotFound =>\n        return Err(anyhow!(\"File does not exist: {}\", path.display())),\n    Err(e) if e.kind() == std::io::ErrorKind::PermissionDenied =>\n        return Err(anyhow!(\"Permission denied: {}\", path.display())),\n    Err(e) => return Err(anyhow!(\"Cannot read file: {}\", e)),\n};","preventionTips":["Pause or await cloud-sync hydration before importing from synced folders.","Ensure the app sandbox retains file access (re-pick per session on macOS).","Replace exists()+metadata() with a single metadata() call to remove the TOCTOU window.","Retry once on transient NotFound - AV and sync tools release files quickly."],"tags":["file","import","filesystem","permissions","toctou","io"],"backgroundTag":"file-access-denied","analyzedSha":"0281737d87d26352fb0adc78c8c0975f691b23d1","analyzedAt":"2026-08-16T20:57:52.567Z","schemaVersion":2},"datasetVersion":"2026-08-16T23:17:17.608Z"}