zeroclaw-labs/zeroclaw · error

AssemblyAI transcription failed: {}

Error message

AssemblyAI transcription failed: {}

What it means

The AssemblyAI poll loop received status "error" for the transcript job: the job was accepted and processed but failed server-side. The 'error' field from the poll body is embedded when present ('unknown transcription error' otherwise). This is terminal — retrying the same audio usually fails again unless the root cause (media format, quota, duration) is fixed.

Source

Thrown at crates/zeroclaw-channels/src/transcription.rs:590

                let error_msg = poll_body["error"].as_str().unwrap_or("unknown poll error");
                bail!("AssemblyAI poll error ({}): {}", poll_status, error_msg);
            }

            let status_str = poll_body["status"].as_str().unwrap_or("unknown");

            match status_str {
                "completed" => {
                    let text = poll_body["text"]
                        .as_str()
                        .context("AssemblyAI response missing 'text'")?
                        .to_string();
                    return Ok(text);
                }
                "error" => {
                    let error_msg = poll_body["error"]
                        .as_str()
                        .unwrap_or("unknown transcription error");
                    bail!("AssemblyAI transcription failed: {}", error_msg);
                }
                _ => {}
            }
        }

        bail!("AssemblyAI transcription timed out after 180s")
    }
}

// ── GoogleSttProvider ───────────────────────────────────────────

/// Google Cloud Speech-to-Text API transcription_provider.
pub struct GoogleSttProvider {
    alias: String,
    api_key: String,
    language_code: String,
}

View on GitHub (pinned to 88bb9c8533)

Solutions

  1. Read the embedded error message — AssemblyAI names the exact cause (e.g. 'unsupported media format', 'duration limit exceeded')
  2. Re-encode the audio to mp3/wav/flac with ffmpeg and retry
  3. For duration-limit errors, split long audio into shorter segments
  4. Check the AssemblyAI dashboard for the failed transcript and account quota

Example fix

# re-encode a problematic voice note before transcribing
ffmpeg -i input.amr -ar 16000 -ac 1 -c:a libmp3lame -b:a 48k input.mp3
Defensive patterns

Strategy: try-catch

Try / catch

match provider.transcribe(&audio, name).await {
    Ok(text) => Ok(text),
    Err(e) if e.to_string().contains("AssemblyAI transcription failed") => {
        // terminal job failure: do NOT blind-retry; read the embedded reason first
        anyhow::bail!("assemblyai rejected the media: {e}")
    }
    other => other,
}

Prevention

When it happens

Trigger: AssemblyAI sets the transcript's status to "error": unsupported or corrupt media (e.g. a video file misrouted as audio, zero-byte audio, unsupported codec), audio duration exceeding the account's limit, or account quota/billing problems.

Common situations: Codec edge cases (unusual AAC/AMR variants from cheap phones), silent/corrupt voice messages downloaded truncated by a proxy, free-tier duration caps exceeded by long recordings.

Related errors


AI-assisted analysis of zeroclaw-labs/zeroclaw@88bb9c8533 (2026-08-23). Data as JSON: /api/errors/b74e3940d8864177. Report an issue: GitHub.