Mintplex-Labs/anything-llm · error
Invalid audio upload. ${err.message}
Error message
Invalid audio upload. ${err.message} What it means
Error from the in-memory audio upload middleware used for transcription (Whisper). It configures multer with memoryStorage, a per-file 25MB limit matching the OpenAI Whisper cap, a fileFilter that rejects any mimetype not starting with 'audio/', and .single('audio'). Any violation returns HTTP 500 with 'Invalid audio upload. <err.message>' — typical err.message values are 'File too large' (LIMIT_FILE_SIZE), 'Only audio uploads are allowed.' (fileFilter), or 'Unexpected field' (wrong part name).
Source
Thrown at server/utils/files/multer.js:189
}
/**
* Handle in-memory audio upload for STT transcription. Audio buffers are
* passed straight to the STT provider so we never persist them to disk.
*/
function handleAudioUpload(request, response, next) {
const upload = multer({
storage: multer.memoryStorage(),
limits: { fileSize: 25 * 1024 * 1024 }, // 25MB matches OpenAI Whisper limit
fileFilter: (_req, file, cb) => {
if (!file.mimetype?.startsWith("audio/"))
return cb(new Error("Only audio uploads are allowed."));
cb(null, true);
},
}).single("audio");
upload(request, response, function (err) {
if (err) {
return response.status(500).json({
success: false,
error: `Invalid audio upload. ${err.message}`,
});
}
next();
});
}
/**
* Handle in-memory image upload for image generation/editing. Buffers are
* passed directly to the image generation provider, never persisted to disk.
*/
function handleImageGenUpload(request, response, next) {
const upload = multer({
storage: multer.memoryStorage(),
limits: { fileSize: 25 * 1024 * 1024 },
fileFilter: (_req, file, cb) => {
if (!file.mimetype?.startsWith("image/"))View on GitHub (pinned to 3aec848f28)
Solutions
- Send the file as the part named 'audio' with a mimetype starting with 'audio/' (e.g. audio/mpeg, audio/wav, audio/webm)
- Compress, trim, or convert the audio so it is under 25MB — this is a hard Whisper-aligned cap
- Re-encode video containers (mp4/mov) to an audio-only format so the mimetype is audio/*
- Send exactly one file part in a well-formed multipart body
Example fix
// before
fd.append('file', videoFile); // part 'file', type video/mp4 -> rejected twice
// after
// extract audio track first, then:
fd.append('audio', audioBlob /* Blob type 'audio/mpeg' */); Defensive patterns
Strategy: validation
Validate before calling
const MAX = 25 * 1024 * 1024;
if (!audioFile.type.startsWith('audio/')) throw new Error('Convert to an audio/* container first');
if (audioFile.size > MAX) throw new Error('Audio exceeds 25MB Whisper cap');
const fd = new FormData();
fd.append('audio', audioFile); Type guard
const isUploadableAudio = (f) =>
f instanceof File && f.type.startsWith('audio/') && f.size <= 25 * 1024 * 1024; Try / catch
if (!res.ok) {
const { error } = await res.json();
if (/File too large/.test(error)) recompressOrTrim();
if (/Only audio uploads/.test(error)) reencodeToAudioContainer();
} Prevention
- Strip video containers to audio-only before upload
- Show the 25MB limit in the recorder UI before the user records an hour
- Set explicit Blob type when uploading recorded chunks (they default to empty mimetype)
When it happens
Trigger: POST multipart to the transcribe/voice endpoint with the part named other than 'audio'; audio file over 25MB; a file whose declared mimetype is video/mp4 or application/octet-stream even though it carries an audio track (the filter checks mimetype, not content).
Common situations: Uploading long recordings that exceed 25MB; phones producing .mp4/.mov containers whose mimetype is video/*; clients naming the part 'file' or 'audioFile'; files sent with a generic application/octet-stream mimetype by a proxy or SDK.
Related errors
- Invalid image upload. ${err.message}
- Failed to load or play TTS message response.
- json?.error || "Failed to transcribe audio."
AI-assisted analysis of Mintplex-Labs/anything-llm@3aec848f28 (2026-08-18).
Data as JSON: /api/errors/342ee266fdeb3830.
Report an issue: GitHub.