{"record":{"id":"27109e583793bd6a","repo":"Mintplex-Labs/anything-llm","slug":"failed-to-transcribe-audio","errorCode":null,"errorMessage":"Failed to transcribe audio.","messagePattern":"Failed to transcribe audio\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"frontend/src/models/system.js","lineNumber":926,"sourceCode":"  /**\n   * Send a recorded audio blob to the configured server-side STT provider\n   * for transcription. Returns the transcribed text or an error string.\n   * @param {Blob} audioBlob - Recorded audio (e.g., audio/webm) to transcribe.\n   * @param {string} [filename] - Filename hint for the upload.\n   * @returns {Promise<{text: string|null, error: string|null}>}\n   */\n  transcribeAudio: async function (audioBlob, filename = \"audio.webm\") {\n    const formData = new FormData();\n    formData.append(\"audio\", audioBlob, filename);\n    return fetch(`${API_BASE}/system/transcribe-audio`, {\n      method: \"POST\",\n      headers: baseHeaders(),\n      body: formData,\n    })\n      .then(async (res) => {\n        const json = await res.json();\n        if (!res.ok)\n          throw new Error(json?.error || \"Failed to transcribe audio.\");\n        return { text: json?.text ?? \"\", error: null };\n      })\n      .catch((e) => ({ text: null, error: e.message }));\n  },\n\n  experimentalFeatures: {\n    liveSync: LiveDocumentSync,\n    agentPlugins: AgentPlugins,\n  },\n  promptVariables: SystemPromptVariable,\n};\n\nexport default System;\n","sourceCodeStart":908,"sourceCodeEnd":940,"githubUrl":"https://github.com/Mintplex-Labs/anything-llm/blob/526360e320da9d1b36074be5ed64fe76e5bbfbbd/frontend/src/models/system.js#L908-L940","documentation":"Thrown by System.transcribeAudio when POST /system/transcribe-audio returns non-2xx. The endpoint receives multipart/form-data with an audio blob and returns { text } on success. The handler reads json.error for the server-side reason and falls back to 'Failed to transcribe audio.' The .catch returns { text: null, error } — note it does not log to console, unlike sibling methods.","triggerScenarios":"Audio blob is empty or in an unsupported container (e.g. audio/webm when only audio/wav is accepted), the configured transcription provider (Whisper) is unreachable or has no API key, the audio exceeds the server's max upload size, or the session expired.","commonSituations":"Browser MediaRecorder produced an empty blob because the user never granted microphone permission or spoke; backend Whisper provider key not configured; nginx/Cloudflare body-size limit smaller than the audio payload; user on a browser that records in a codec the server cannot decode.","solutions":["Validate the audioBlob has non-zero size and a supported MIME type before posting.","Confirm the backend transcription provider (Whisper) is configured with a valid API key.","Raise the reverse-proxy client_max_body_size if the upload is being truncated.","Add a console.error in the .catch (currently missing) so failures are visible in DevTools."],"exampleFix":"// before\ntranscribeAudio: async function (audioBlob, filename = \"audio.webm\") {\n  const formData = new FormData();\n  formData.append(\"audio\", audioBlob, filename);\n  return fetch(...);\n}\n\n// after — guard empty blob\nif (!audioBlob || audioBlob.size === 0) {\n  return { text: null, error: \"Audio recording is empty.\" };\n}","handlingStrategy":"validation","validationCode":"// Reject empty or unsupported blobs before uploading.\nfunction isValidAudioBlob(blob, allowed = ['audio/webm','audio/wav','audio/mp3','audio/ogg']) {\n  return blob && blob.size > 0 && allowed.includes(blob.type);\n}","typeGuard":"function isTranscriptionSuccess(x): x is { text: string; error: null } {\n  return x && typeof x.text === 'string' && x.error === null;\n}","tryCatchPattern":"if (!isValidAudioBlob(audioBlob)) {\n  return { text: null, error: 'Audio recording is empty or unsupported.' };\n}\nconst { text, error } = await System.transcribeAudio(audioBlob, filename);\nif (error) showToast(error);","preventionTips":["Check audioBlob.size > 0 before posting (MediaRecorder can yield empty blobs).","Confirm the backend transcription provider is configured.","Raise reverse-proxy body-size limits for audio uploads."],"tags":["frontend","api-client","audio","whisper","upload","network"],"backgroundTag":null,"analyzedSha":"526360e320da9d1b36074be5ed64fe76e5bbfbbd","analyzedAt":"2026-08-13T01:45:47.170Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}