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

  1. Send the file as the part named 'audio' with a mimetype starting with 'audio/' (e.g. audio/mpeg, audio/wav, audio/webm)
  2. Compress, trim, or convert the audio so it is under 25MB — this is a hard Whisper-aligned cap
  3. Re-encode video containers (mp4/mov) to an audio-only format so the mimetype is audio/*
  4. 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

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


AI-assisted analysis of Mintplex-Labs/anything-llm@3aec848f28 (2026-08-18). Data as JSON: /api/errors/342ee266fdeb3830. Report an issue: GitHub.