{"record":{"id":"5aef7473d6d8325b","repo":"Mintplex-Labs/anything-llm","slug":"invalid-audio-file-error-message","errorCode":null,"errorMessage":"Invalid audio file: ${error.message}","messagePattern":"Invalid audio file: (.+?)","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"warning","filePath":"collector/utils/WhisperProviders/localWhisper.js","lineNumber":88,"sourceCode":"      if (!fs.existsSync(outFolder))\n        fs.mkdirSync(outFolder, { recursive: true });\n\n      const outputFile = path.resolve(outFolder, `${v4()}.wav`);\n      const success = await ffmpeg.convertAudioToWav(sourcePath, outputFile);\n      if (!success)\n        throw new Error(\n          \"[Conversion Failed]: Could not convert file to .wav format!\"\n        );\n\n      buffer = fs.readFileSync(outputFile);\n      fs.rmSync(outputFile);\n\n      const wavFile = new wavefile.WaveFile(buffer);\n      try {\n        this.#validateAudioFile(wavFile);\n      } catch (error) {\n        this.#log(`Audio validation failed: ${error.message}`);\n        throw new Error(`Invalid audio file: ${error.message}`);\n      }\n\n      // Although we use ffmpeg to convert to the correct format (16k hz 32f),\n      // different versions of ffmpeg produce different results based on the\n      // environment. To ensure consistency, we convert to the correct format again.\n      wavFile.toBitDepth(\"32f\");\n      wavFile.toSampleRate(16000);\n\n      let audioData = wavFile.getSamples();\n      if (Array.isArray(audioData)) {\n        if (audioData.length > 1) {\n          const SCALING_FACTOR = Math.sqrt(2);\n\n          // Merge channels into first channel to save memory\n          for (let i = 0; i < audioData[0].length; ++i) {\n            audioData[0][i] =\n              (SCALING_FACTOR * (audioData[0][i] + audioData[1][i])) / 2;\n          }","sourceCodeStart":70,"sourceCodeEnd":106,"githubUrl":"https://github.com/Mintplex-Labs/anything-llm/blob/526360e320da9d1b36074be5ed64fe76e5bbfbbd/collector/utils/WhisperProviders/localWhisper.js#L70-L106","documentation":"Wrapper thrown when #validateAudioFile raises (errors 25/26/27). #convertToWavAudioData catches the validation error, logs it, and re-throws with an \"Invalid audio file:\" prefix. This is the surfaced form of the three validation errors.","triggerScenarios":"Any of the three validation failures (low sample rate, >4 h duration, projected samples too high) inside #convertToWavAudioData triggers the catch, which re-wraps the message.","commonSituations":"Bad/corrupt audio; a pre-existing WAV not normalized by ffmpeg; extremely long recordings.","solutions":["Parse the inner message to determine which validation failed and act (re-encode, split, reject).","Re-encode the source through ffmpeg to 16 kHz mono and retry.","Split long files into <4 h chunks."],"exampleFix":"// before\nthrow new Error(`Invalid audio file: ${error.message}`);\n\n// after — typed error for programmatic handling\nconst err = new Error(`Invalid audio file: ${error.message}`);\nerr.cause = error;\nerr.code = error.message.includes(\"sample rate\") ? \"LOW_SAMPLE_RATE\"\n  : error.message.includes(\"duration\") ? \"TOO_LONG\" : \"TOO_MANY_SAMPLES\";\nthrow err;","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try { await localWhisper.processFile(filePath, name); }\ncatch (e) {\n  if (e.message.startsWith(\"Invalid audio file:\")) {\n    const reason = e.message.slice(\"Invalid audio file:\".length).trim();\n    /* branch on reason: re-encode, split, or reject */\n  }\n  throw e;\n}","preventionTips":["Pre-normalize audio to 16 kHz mono before Whisper.","Surface the inner validation reason to the user.","Split long files upstream."],"tags":["audio","whisper","validation","error-wrapping"],"backgroundTag":null,"analyzedSha":"526360e320da9d1b36074be5ed64fe76e5bbfbbd","analyzedAt":"2026-08-13T01:45:47.170Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}