{"record":{"id":"f85aeaee4c1acc5d","repo":"Mintplex-Labs/anything-llm","slug":"deepgram-transcription-failed-response-status","errorCode":null,"errorMessage":"Deepgram transcription failed (${response.status}) - ${errBody}","messagePattern":"Deepgram transcription failed \\((.+?)\\) - (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"server/utils/SpeechToText/deepgram/index.js","lineNumber":61,"sourceCode":"   * @returns {Promise<string>} The transcribed text.\n   */\n  async transcribe(audioBuffer, filename = \"audio.webm\") {\n    const url = new URL(this.endpoint);\n    url.searchParams.set(\"model\", this.model);\n    url.searchParams.set(\"smart_format\", \"true\");\n\n    return await fetch(url.toString(), {\n      method: \"POST\",\n      headers: {\n        Authorization: `Token ${this.apiKey}`,\n        \"Content-Type\": this.#contentTypeFromFilename(filename),\n      },\n      body: audioBuffer,\n    })\n      .then(async (response) => {\n        if (!response.ok) {\n          const errBody = await response.text().catch(() => \"\");\n          throw new Error(\n            `Deepgram transcription failed (${response.status}) - ${errBody}`\n          );\n        }\n        return response.json();\n      })\n      .then((result) => {\n        return (\n          result?.results?.channels?.[0]?.alternatives?.[0]?.transcript ?? \"\"\n        );\n      })\n      .catch((error) => {\n        this.#log(`Deepgram transcription failed - ${error.message}`);\n        throw new Error(`Deepgram transcription failed - ${error.message}`);\n      });\n  }\n}\n\nmodule.exports = { DeepgramSTT };","sourceCodeStart":43,"sourceCodeEnd":79,"githubUrl":"https://github.com/Mintplex-Labs/anything-llm/blob/3aec848f2885144aa8f1e53b9731a04310d5d558/server/utils/SpeechToText/deepgram/index.js#L43-L79","documentation":"DeepgramSTT POSTs the raw audio buffer to https://api.deepgram.com/v1/listen with an Authorization: Token header; when the response status is not ok, it reads the body as text and throws this templated error embedding the HTTP status and Deepgram's error body. The status code identifies the failure class (401 auth, 400 bad request/model, 413 payload, 429 rate limit, 5xx upstream).","triggerScenarios":"401/403 with an invalid or revoked STT_DEEPGRAM_API_KEY; 400 when the Content-Type mapped from the file extension is wrong, the audio is corrupt, or STT_DEEPGRAM_MODEL names a nonexistent model; 413 for very large files; 429 when the key's rate/concurrency limit is hit.","commonSituations":"Expired or mis-pasted Deepgram key; uploading webm/ogg files whose extension mapping produces a Content-Type Deepgram rejects; setting STT_DEEPGRAM_MODEL to a deprecated or typo'd model name; bursting many transcriptions on a free-tier key.","solutions":["Match the embedded status: 401/403 → fix STT_DEEPGRAM_API_KEY; 400 → check model name and audio format; 429 → slow down or upgrade the Deepgram plan; 5xx → retry shortly","Read the errBody fragment in the message — Deepgram states the exact reason (e.g. invalid model, malformed audio)","Verify STT_DEEPGRAM_MODEL is a currently valid model (default nova-3)","For very long recordings, split the audio into smaller chunks before sending"],"exampleFix":"# model typo producing 400s\n# before (.env)\nSTT_DEEPGRAM_MODEL=nova-2-general\n\n# after (.env)\nSTT_DEEPGRAM_MODEL=nova-3","handlingStrategy":"retry","validationCode":"// Nothing to pre-validate beyond the key; assert it to fail early on the auth class\nif (!process.env.STT_DEEPGRAM_API_KEY) throw new Error('Missing STT_DEEPGRAM_API_KEY');","typeGuard":null,"tryCatchPattern":"const RETRYABLE = new Set([408, 429, 500, 502, 503, 504]);\nfunction parseDeepgramStatus(err) {\n  const m = err.message.match(/Deepgram transcription failed \\((\\d+)\\)/);\n  return m ? Number(m[1]) : null;\n}\nfor (let attempt = 0; attempt < 3; attempt++) {\n  try { return await stt.process(audioBuffer, filename); }\n  catch (err) {\n    const status = parseDeepgramStatus(err);\n    if (status && RETRYABLE.has(status)) { await sleep(2 ** attempt * 500); continue; }\n    throw err; // 401/400/413 are permanent — surface them\n  }\n}","preventionTips":["Inspect the embedded HTTP status before retrying — only 408/429/5xx are worth retrying","Keep STT_DEEPGRAM_MODEL pinned to a documented valid model name","Chunk long audio and enforce Deepgram size limits before upload"],"tags":["deepgram","speech-to-text","http-status","api-error"],"backgroundTag":"api-error-response","analyzedSha":"3aec848f2885144aa8f1e53b9731a04310d5d558","analyzedAt":"2026-08-18T10:02:21.017Z","contentChangedAt":"2026-08-18T10:02:21.017Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}