Skip to main content

Troubleshooting: transcription, synthesis, and deepfake failures

This page owns the failure codes for every produce-then-read pipeline that turns speech into text or text into speech: the STT (speech-to-text) step, the TTS (text-to-speech) step, the voice and video transcript surfaces, the AI summary/eval steps running an LLM over those transcripts, and the synthetic-voice classifier on voice-biometrics enrollment. Each code tells you which stage broke, and the stage tells you who can fix it — the produce-side codes point at upstream provider health, the read-side codes point at a retry-safe surface failure. Read error.code off the envelope; the matrix below maps each code to the stage that raised it and to the section with the cause table, envelope sample, and ticket checklist.

Code matrix — symptom to section

STT — upstream and codec

STT_TRANSCRIPTION_FAILED (500) means the speech-to-text provider either did not answer or returned an unusable result, on the standalone POST /api/v1/stt/transcribe surface or inside an agent pipeline turn. Orbit routes STT through Deeway primary (the provider named in the FAQ’s pipeline) with a failover chain the agent layer re-orders per caller-requested language; a 500 on this surface fires only when every leg came back empty or errored. Codec matters here for standalone uploads: when the source call negotiates a transcoding-heavy codec, the gateway funnels PCMU/PCMA frames through a decode buffer before STT; a misalignment at that boundary produces untranscribable audio rather than a provider failure. Confirm the negotiated codec on the call — OPUS, PCMU (G.711 µ-law), or PCMA (G.711 A-law) are the supported set per the FAQ codec list — and re-send a clip in one of those before treating the failure as provider-side.

Cause table

Retry-safety

Safe to retry — a transcribe call writes nothing before the provider answers (the audio upload cap is enforced before the provider hop). Use exponential backoff over tens of seconds; a tight loop spends your rate limit against the same outage.

Envelope sample

Ticket checklist

  1. The code (STT_TRANSCRIPTION_FAILED) and the endpoint you called (/api/v1/stt/transcribe).
  2. The codec the source call negotiated (OPUS / PCMU / PCMA) or the upload format you passed.
  3. Request IDs and timestamps for two or three failing calls — that brackets the provider window.
  4. Your organization ID (Settings → Organization, or organizationId from GET /api/v1/me).

TTS — primary and fallback

TTS_SYNTHESIS_FAILED (500) fires on POST /api/v1/tts/synthesize (and on the agent-turn path) when synthesis failed on every provider leg. The FAQ’s STT → LLM → TTS pipeline routes TTS through Cartesia as the primary provider; the agent pipeline falls to an ElevenLabs leg when one is configured, with a per-leg timeout budget set in milliseconds rather than a blocking wait. A 500 means both legs failed or no fallback was configured. Voice matters most here: the most common tenant-side cause is a voice_id the provider rejects — a passed id that no longer exists on the configured provider, or an agent whose saved voice config points at a provider the organization has not activated. Retry once on the same id only after re-reading the agent’s voice configuration; otherwise verify the configured primary endpoint and the fallback leg before retrying again.

Cause table

Retry-safety

Safe to retry — synthesis writes nothing before the provider answers. The one non-retry case is the bad voice_id: a retry against the same rejected id fails identically, so fix the voice config first.

Envelope sample

Ticket checklist

  1. The code (TTS_SYNTHESIS_FAILED) and the endpoint (/api/v1/tts/synthesize, or the agent-turn path it rode on).
  2. The voice id you passed (or default when omitted).
  3. Whether the failure is primary-leg-only or all-legs — the split decides between provider drift and chain exhaustion.
  4. Request IDs and timestamps for failing calls, plus your organization ID.

Transcript — not yet produced

All three codes here are 422 pre-check verdicts, not failures: the summary (or live-ask) service looked for a usable transcript, found none, and refused. That is distinct from the 5xx read/write failures in the next section — those are transient server-side faults you retry; a 422 here is a readiness state you resolve by waiting or by enabling capture.
  • CALL_TRANSCRIPT_UNAVAILABLE fires on POST /api/v1/voice/calls/:id/summary when the call has no usable transcript yet — typically because the recording→transcription producer has not finished, or transcription was disabled on the call.
  • VIDEO_LIVE_TRANSCRIPT_UNAVAILABLE fires on the in-meeting live-assist endpoint (POST /api/v1/video/rooms-scheduled/:id/ask) when the room has captured no captions yet — captions off, or too little speech so far.
  • VIDEO_TRANSCRIPT_UNAVAILABLE fires on POST /api/v1/video/sessions/:id/summary when the meeting has no usable transcript — the meeting is still live, or closed captions were never enabled.

Cause table

For voice calls whose transcript never lands at all, check the production side (recording/transcription enablement on the call flow) before re-issuing the summary; for video, confirm the room had captions/transcription enabled before the call.

Envelope sample

Ticket checklist

Only escalate when the transcript probe has been re-checked after the producer finished:
  1. The code (one of the three above) and the endpoint.
  2. The call id / session_id / room id of the missing transcript.
  3. Whether captions or transcription were enabled on that call or room, and how long since it ended.
  4. Your organization ID.

Transcript reads and exports — retry-safe

The hosted video transcript surfaces read the captured record a meeting (or the correction write) produced. The three 5xx codes below mean that read/write hit a transient server fault — a tenant-schema blip, a DB pool exhaustion moment, or an export-pipeline race — and the request never partially applied anything. All three are safe to retry.
  • VIDEO_TRANSCRIPT_LIST_FAILED (500) on GET /api/v1/video/rooms-scheduled/:id/transcripts — the paginated replay surface failed to load the transcript rows.
  • VIDEO_TRANSCRIPT_EXPORT_FAILED (500) on GET /api/v1/video/rooms-scheduled/:id/transcripts/export — the caption-file export (WebVTT/SRT/digest) failed.
  • VIDEO_TRANSCRIPT_CORRECT_FAILED (500) on the caption-correction surface (PATCH /api/v1/video/rooms-scheduled/:id/transcripts/:transcriptId or the POST-correction variant on the same room) — the write failed.
This split is the diagnostic the producer-versus-read ladder gives you: a 422 from the previous section is a produce-side readiness verdict (wait or enable captions), a 5xx here is a read-side fault (retry, then escalate if it persists — the pure-read path (LIST_FAILED, UNAVAILABLE) never touches the write path (CORRECT_FAILED, EXPORT_FAILED).

Cause table

Envelope sample

Ticket checklist

  1. The code (one of the three above) and the endpoint.
  2. The room id you were reading (or the transcriptId on a correction write).
  3. Whether every transcript surface fails or only one — the split separates a room-scoped condition from a surface-scoped one.
  4. Your organization ID.
DEEPFAKE_DETECTED (422) is the synthetic-voice family classifier on the voice-biometrics enrollment surfaces: the Resemble Detect synthetic-speech score on the sample you submitted met or exceeded the platform threshold, so the enrollment (or the clone-create request) refused. It is a classifier verdict on the media you handed us — not a rights problem, not a consent problem. Distinguish it from the consent gates deliberately, because the two families interact. The consent family (AI voice consent guard, FCC_AI_VOICE_WRITTEN_CONSENT_REQUIRED on the consent-check surfaces before dial) is a recipient-consent record check — a written consent record on the recipient must grant outbound synthetic voice content. The deepfake classifier here is a media-authenticity check — the audio sample itself was flagged as synthetic or cloned. Pasting a full-consent URL on an enrollment the classifier refused still returns the same 422; the fix is a genuine human-speech sample, not another consent record. For the provenance side — how AI-generated output carries content credentials so recipients and reviewers can check a provenance claim — see Synthetic-media provenance. The consent gates and the deepfake classifier both sit under the synthetic-voice family umbrella, but this error carries only the classifier verdict: the sample did not authenticate as human-performable speech. Allowed voice clones enroll through the consent-registered speech (create a voice clone) before any watermark or synthesis runs, and the classifier applies to the enrollment sample itself.

Cause table

Retry-safety

Do not retry in a loop — every retry with the same flagged sample fails identically. Resolve the sample first, then re-submit once.

Envelope sample

Ticket checklist

  1. The code (DEEPFAKE_DETECTED) and the enrollment endpoint.
  2. A short sample-description for the audio (recording method, speaker) — confirm it is a genuine human sample, not TTS.
  3. Whether the rejection happens on enrollment or on clone-create — the split separates classifier verdicts from clone-create pathing.
  4. Your organization ID. Consent gates are a separate family; only include a consent record reference if you have already verified it.

LLM summaries — malformed output

CALL_SUMMARY_LLM_MALFORMED (502) and VIDEO_SUMMARY_LLM_MALFORMED (502) fire when the LLM endpoint answered, but its reply failed validation — the summary service could not parse the expected JSON shape from the model output, after retries at the service layer. The prompt was fine; the model’s output was not. Model drift under provider load is the usual cause, and the failure is safe to retry: the request writes nothing before the summary is accepted, and a retry rides the same transcript probe. A model endpoint that has recovered answers the retry cleanly. When the retries you issued keep returning the same 502, treat that window as a provider incident and escalate — with the request IDs you captured, the recovery is minutes rather than hours. The follow-on watch item is the 503 sibling LLM_PROVIDER_UNCONFIGURED — a deployment with no LLM key configured does not reach the malformed stage; the summary surface raises the unconfigured code before any model call. Escalate immediately there rather than retrying.

Cause table

Retry-safety

Safe to retry. Service-layer retries are exhausted before the 502 is surfaced, but a bounded manual backoff (three attempts over tens of seconds) is the right cadence; a tight loop spends your rate limit against the same malformed output.

Envelope sample

Ticket checklist

  1. The code (CALL_SUMMARY_LLM_MALFORMED or VIDEO_SUMMARY_LLM_MALFORMED) and the endpoint.
  2. Request IDs and timestamps for the failing calls — that brackets the provider window.
  3. The call id / session id you were summarizing.
  4. Your organization ID.

Do NOT retry these

  • Do not retry DEEPFAKE_DETECTED in a loop. Every retry signs the same flagged sample over the classifier and fails identically; only a new genuine sample changes the verdict.
  • Do not submit longer samples to beat STT/TTS timeouts. A rejected voice_id or an unsupported codec is deterministic — a retry with the same payload reads identically on every attempt.
  • Do not treat a 5xx transcript read as a transcript-absence verdict. A VIDEO_TRANSCRIPT_LIST_FAILED or CORRECT_FAILED/EXPORT_FAILED is a surface fault — retry it before you escalate; only the 422 family is a produce-side readiness verdict.
  • Do not re-synthesize the same voice_id. A rejected voice id is deterministic; fix the agent’s voice config before re-issuing the call.

See also