{"record":{"id":"a3582d9097be5929","repo":"Zackriya-Solutions/meetily","slug":"unsupported-format-supported","errorCode":null,"errorMessage":"Unsupported format: .{}. Supported: {}","messagePattern":"Unsupported format: \\.(.+?)\\. Supported: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"frontend/src-tauri/src/audio/import.rs","lineNumber":135,"sourceCode":"}\n\n/// Validate an audio file and return its info using metadata-only approach\n/// Falls back to full decode if metadata is unavailable\npub fn validate_audio_file(path: &Path) -> Result<AudioFileInfo> {\n    // Check file exists\n    if !path.exists() {\n        return Err(anyhow!(\"File does not exist: {}\", path.display()));\n    }\n\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        ));","sourceCodeStart":117,"sourceCodeEnd":153,"githubUrl":"https://github.com/Zackriya-Solutions/meetily/blob/0281737d87d26352fb0adc78c8c0975f691b23d1/frontend/src-tauri/src/audio/import.rs#L117-L153","documentation":"validate_audio_file (import.rs:135) rejects the file because its lowercased extension is not in AUDIO_EXTENSIONS (the whitelist from super::constants - mp3/m4a/wav/mp4-class containers plus the ffmpeg-handled mkv/webm/wma set). This is extension-based gating only: the file is never opened first, so a good audio file with an unusual or missing extension is rejected, while a mislabeled file with a whitelisted extension passes this check and fails later in decode.","triggerScenarios":"Passing .flac/.ogg/.opus/.aac/.amr/.aiff files (not on the list); files with no extension at all (extension() is None, unwrap_or_default gives an empty string that never matches); double extensions like .mp4.part or .wav.download during an incomplete transfer; names with a trailing space after the extension.","commonSituations":"Users importing voice memos in FLAC/OGG/OPUS (common from Android recorders and open-source tools); recordings renamed by cloud sync tools; .m4a exports labeled .aac by some apps; users typing a filename manually.","solutions":["Re-encode/wrap into a supported container: ffmpeg -i input.flac -c:a aac output.m4a (or -ar 16000 -ac 1 wav).","Rename only when the container actually matches a supported codec - renaming .ogg to .mp3 passes this gate then fails in decode.","If you control the app build, extend AUDIO_EXTENSIONS in audio/constants.rs AND ensure Symphonia or the ffmpeg pre-conversion list in decoder.rs actually supports the codec.","Pre-filter in the UI dialog (filters list) so unsupported extensions can never be selected."],"exampleFix":"# before: unsupported extension rejected at the gate\n# (renaming alone is a trap: decode will fail later)\n\n# after: transcode to a whitelisted container/codec\nffmpeg -i voice-memo.flac -c:a aac -b:a 128k out.m4a   # import out.m4a","handlingStrategy":"validation","validationCode":"// Frontend: constrain the picker so unsupported extensions cannot be chosen\nimport { open } from '@tauri-apps/plugin-dialog';\nconst picked = await open({\n  filters: [{ name: 'Audio', extensions: ['mp3','m4a','wav','mp4','mkv','webm','wma'] }],\n});","typeGuard":"// TypeScript: mirror the Rust whitelist before invoking\nconst AUDIO_EXTENSIONS = ['mp3','m4a','wav','mp4','mkv','webm','wma'];\nconst isSupportedAudioFile = (p: string) =>\n  AUDIO_EXTENSIONS.includes(p.split('.').pop()?.toLowerCase() ?? '');","tryCatchPattern":"// Catch and guide the user to convert, rather than showing a raw error\ntry { await invoke('validate_audio_file', { path }); }\ncatch (e) {\n  if (String(e).startsWith('Unsupported format')) suggestTranscode(e);\n  else throw e;\n}","preventionTips":["Filter the file dialog to AUDIO_EXTENSIONS.","Convert FLAC/OGG/OPUS/AAC to m4a/wav with ffmpeg before import.","Never fix by renaming alone - the extension gate is followed by real decoding.","If you own the build, extend AUDIO_EXTENSIONS AND the Symphonia/ffmpeg support behind it."],"tags":["file","import","validation","unsupported-format","file-extension"],"backgroundTag":"unsupported-file-format","analyzedSha":"0281737d87d26352fb0adc78c8c0975f691b23d1","analyzedAt":"2026-08-16T20:57:52.567Z","schemaVersion":2},"datasetVersion":"2026-08-16T23:17:17.608Z"}