openai/codex · error
unsupported audio format
Error message
unsupported audio format
What it means
io::Error(ErrorKind::InvalidData, 'unsupported audio format') from snapshot_local_user_input (codex-rs/protocol/src/local_media.rs:37-39): a UserInput::LocalAudio path failed audio_mime_for_path (local_media.rs:74-89), which maps only .wav, .mp3, .m4a, .webm, and .ogg (case-insensitive) to MIME types. Detection is purely extension-based - content is never sniffed - and files with any other or missing extension are rejected before being read.
Source
Thrown at codex-rs/protocol/src/local_media.rs:38
match input {
UserInput::LocalImage { path, detail } => {
let image_detail = *detail;
let mode = match image_detail {
Some(ImageDetail::Original) => PromptImageMode::Original,
Some(ImageDetail::Auto | ImageDetail::Low | ImageDetail::High) | None => {
PromptImageMode::ResizeToFit
}
};
let file_bytes = read_bounded_local_media(path, MAX_PROMPT_IMAGE_INPUT_BYTES, "image")?;
let image = load_for_prompt_bytes(path, file_bytes, mode).map_err(io::Error::other)?;
*input = UserInput::Image {
image_url: image.into_data_url(),
detail: image_detail,
};
}
UserInput::LocalAudio { path } => {
let mime = audio_mime_for_path(path).ok_or_else(|| {
io::Error::new(io::ErrorKind::InvalidData, "unsupported audio format")
})?;
let file_bytes = read_bounded_local_media(path, MAX_PROMPT_AUDIO_INPUT_BYTES, "audio")?;
*input = UserInput::Audio {
audio_url: data_url_from_bytes(mime, &file_bytes),
};
}
UserInput::Text { .. }
| UserInput::Image { .. }
| UserInput::Audio { .. }
| UserInput::Skill { .. }
| UserInput::Mention { .. } => {}
}
Ok(())
}
fn read_bounded_local_media(path: &Path, max_bytes: usize, kind: &str) -> io::Result<Vec<u8>> {
let file = std::fs::File::open(path)?;
if file.metadata()?.len() > max_bytes as u64 {View on GitHub (pinned to 339751715c)
Solutions
- Convert the audio to a supported container (WAV, MP3, M4A, WebM, or OGG), e.g. ffmpeg -i in.flac out.mp3.
- If the content is already a supported format but misnamed, rename it so the extension matches the actual container.
- Verify the final extension before queueing - matching is extension-only, so the name must agree with the bytes.
Example fix
// before: attaching an unsupported file
UserInput::LocalAudio { path: Path::new("/tmp/interview.flac").into() }
// snapshot_local_user_input -> InvalidData: unsupported audio format
// after: convert to a supported format first
// ffmpeg -i interview.flac interview.mp3
UserInput::LocalAudio { path: Path::new("/tmp/interview.mp3").into() } Defensive patterns
Strategy: validation
Validate before calling
const SUPPORTED: &[&str] = &["wav", "mp3", "m4a", "webm", "ogg"];
fn audio_supported(path: &Path) -> bool {
path.extension()
.and_then(|e| e.to_str())
.is_some_and(|e| SUPPORTED.iter().any(|s| e.eq_ignore_ascii_case(s)))
}
// gate before snapshotting:
if !audio_supported(&path) {
reject_with_hint(&path);
} Type guard
fn is_unsupported_audio(err: &io::Error) -> bool {
err.kind() == io::ErrorKind::InvalidData
&& err.to_string().contains("unsupported audio format")
} Try / catch
match snapshot_local_user_input(&mut input) {
Err(e) if e.kind() == io::ErrorKind::InvalidData && e.to_string().contains("unsupported audio format") => {
// tell the user which formats are accepted (wav/mp3/m4a/webm/ogg)
}
other => other?,
} Prevention
- Filter file pickers to supported audio extensions.
- Convert uploads with ffmpeg before queueing them.
- Remember detection is extension-only: name files to match their true container.
When it happens
Trigger: Queueing UserInput::LocalAudio { path } (via prepare_queued_user_input / snapshot_local_user_input) whose extension is outside wav/mp3/m4a/webm/ogg - for example .flac, .aac, .opus, .txt, or no extension at all.
Common situations: Users attach FLAC or AAC recordings; downloads arrive with unusual extensions; files saved without extensions; double extensions like .mp3.txt.
Related errors
- {kind} input exceeds {max_bytes} bytes
- filename '{filename}' {reason}
- ad-hoc note must not be empty
- path '{path}' {reason}
- line_offset must be a 1-indexed line number
AI-assisted analysis of openai/codex@339751715c (2026-08-25).
Data as JSON: /api/errors/0e1228e89d6e6cee.
Report an issue: GitHub.