{"record":{"id":"252851b5580bb735","repo":"Mintplex-Labs/anything-llm","slug":"audio-conversion-failed","errorCode":null,"errorMessage":"Audio conversion failed.","messagePattern":"Audio conversion failed\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"server/utils/SpeechToText/helpers.js","lineNumber":26,"sourceCode":" * Convert an audio buffer to a 16kHz mono WAV buffer via the collector's\n * FFMPEG wrapper. Use this when the downstream STT provider (e.g. Lemonade)\n * runs a whisper.cpp backend that rejects webm/opus input.\n * @param {Buffer} audioBuffer - Source audio buffer.\n * @param {string} extension - Source file extension including the leading dot (e.g. \".webm\").\n * @returns {Promise<Buffer>} The converted WAV buffer.\n */\nasync function convertAudioBufferToWav(audioBuffer, extension) {\n  let wavPath = null;\n  const sourceFilename = `stt-${v4()}${extension}`;\n  const sourcePath = path.resolve(hotdirPath, sourceFilename);\n  if (!isWithin(hotdirPath, sourcePath))\n    throw new Error(\"Source path is outside the hotdir.\");\n\n  try {\n    await fs.writeFile(sourcePath, audioBuffer);\n    const result = await new CollectorApi().convertAudioToWav(sourceFilename);\n    if (!result?.success || !result?.wavFilename)\n      throw new Error(result?.reason || \"Audio conversion failed.\");\n\n    wavPath = path.resolve(hotdirPath, result.wavFilename);\n    return await fs.readFile(wavPath);\n  } finally {\n    await fs.rm(sourcePath, { force: true }).catch(() => {});\n    if (wavPath) await fs.rm(wavPath, { force: true }).catch(() => {});\n  }\n}\n\nmodule.exports = { convertAudioBufferToWav };\n","sourceCodeStart":8,"sourceCodeEnd":37,"githubUrl":"https://github.com/Mintplex-Labs/anything-llm/blob/526360e320da9d1b36074be5ed64fe76e5bbfbbd/server/utils/SpeechToText/helpers.js#L8-L37","documentation":"Thrown by convertAudioBufferToWav when the collector's convertAudioToWav call did not return {success:true, wavFilename}, and result.reason was also falsy so the generic message is used. This function writes the source audio to the hotdir, asks the collector (FFMPEG wrapper) to convert it to WAV, and reads the result back. The generic message means the collector returned neither a reason nor a usable filename.","triggerScenarios":"The collector microservice is not running or unreachable; FFMPEG is not installed in the collector container; the source audio codec is unsupported or the buffer is empty/corrupt; the collector returned {success:false} with no reason field.","commonSituations":"Collector container down or unhealthy; FFMPEG missing from the collector image; webm/opus input that FFMPEG cannot decode without additional libs; file system permissions on the hotdir; extension passed without a leading dot.","solutions":["Check that the collector service is running and healthy (it is a separate process/container from the server).","Verify FFMPEG is installed in the collector container (ffmpeg -version).","Inspect collector logs for the actual conversion error, since result.reason is empty here.","Ensure the extension argument includes the leading dot (e.g. '.webm') and the audioBuffer is non-empty.","Confirm the hotdir path is writable and the source file was actually written."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// Pre-check the collector is reachable before attempting conversion.\nconst healthy = await fetch(`${process.env.COLLECTOR_ENDPOINT || \"http://collector\"}/api/system-health`)\n  .then((r) => r.ok)\n  .catch(() => false);\nif (!healthy) throw new Error(\"Collector service is unreachable; audio conversion will fail.\");","typeGuard":null,"tryCatchPattern":"try {\n  return await convertAudioBufferToWav(audioBuffer, extension);\n} catch (e) {\n  logger.error(\"WAV conversion failed:\", e.message);\n  throw new Error(\"Could not convert audio for transcription. Is the collector + FFMPEG available?\");\n}","preventionTips":["Keep the collector container healthy and FFMPEG installed in its image.","Pass the extension with a leading dot and ensure the buffer is non-empty.","Log collector-side conversion errors so result.reason is populated for the next caller."],"tags":["stt","audio","ffmpeg","collector","conversion"],"backgroundTag":null,"analyzedSha":"526360e320da9d1b36074be5ed64fe76e5bbfbbd","analyzedAt":"2026-08-13T01:45:47.170Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}