{"record":{"id":"ba8b04e02e50b5bd","repo":"zeroclaw-labs/zeroclaw","slug":"assemblyai-poll-error","errorCode":null,"errorMessage":"AssemblyAI poll error ({}): {}","messagePattern":"AssemblyAI poll error \\((.+?)\\): (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/zeroclaw-channels/src/transcription.rs","lineNumber":573,"sourceCode":"            tokio::time::sleep(poll_interval).await;\n\n            let poll_resp = client\n                .get(&poll_url)\n                .header(\"Authorization\", &self.api_key)\n                .timeout(std::time::Duration::from_secs(30))\n                .send()\n                .await\n                .context(\"Failed to poll AssemblyAI transcription\")?;\n\n            let poll_status = poll_resp.status();\n            let poll_body: serde_json::Value = poll_resp\n                .json()\n                .await\n                .context(\"Failed to parse AssemblyAI poll response\")?;\n\n            if !poll_status.is_success() {\n                let error_msg = poll_body[\"error\"].as_str().unwrap_or(\"unknown poll error\");\n                bail!(\"AssemblyAI poll error ({}): {}\", poll_status, error_msg);\n            }\n\n            let status_str = poll_body[\"status\"].as_str().unwrap_or(\"unknown\");\n\n            match status_str {\n                \"completed\" => {\n                    let text = poll_body[\"text\"]\n                        .as_str()\n                        .context(\"AssemblyAI response missing 'text'\")?\n                        .to_string();\n                    return Ok(text);\n                }\n                \"error\" => {\n                    let error_msg = poll_body[\"error\"]\n                        .as_str()\n                        .unwrap_or(\"unknown transcription error\");\n                    bail!(\"AssemblyAI transcription failed: {}\", error_msg);\n                }","sourceCodeStart":555,"sourceCodeEnd":591,"githubUrl":"https://github.com/zeroclaw-labs/zeroclaw/blob/88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc/crates/zeroclaw-channels/src/transcription.rs#L555-L591","documentation":"Step three of the AssemblyAI pipeline: the poll loop GETs the transcript status endpoint, and one poll returned non-2xx. A single failed HTTP poll aborts the whole transcription immediately (the code bails instead of skipping the round), even if the job itself is fine. The status and body 'error' text are embedded.","triggerScenarios":"GET /v2/transcript/{id} returns non-success during the polling loop: 401 invalid api_key, 404 unknown/expired transcript id, 429 rate limited, 5xx transient — each of these immediately fails the transcription.","commonSituations":"A brief network hiccup or a 429 during the poll window kills an otherwise healthy job; AssemblyAI returning 404 for a transcript purged after 30 days is not an issue here, but a 404 right after creation indicates an account/region mismatch; polling burst from many concurrent transcriptions tripping rate limits.","solutions":["429 — space out concurrent transcriptions; AssemblyAI's poll loop already sleeps between rounds, but many parallel jobs multiply request volume","5xx — retry the whole transcribe(); the upload will be repeated but the job usually succeeds","404 — verify the api_key belongs to the account that created the transcript (no region-split keys)","401 — update the api_key in [transcription.assemblyai]"],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"match provider.transcribe(&audio, name).await {\n    Ok(text) => Ok(text),\n    Err(e) if e.to_string().contains(\"AssemblyAI poll error\") => {\n        // a single failed poll kills a healthy job — retry the whole transcription\n        retry_with_backoff(|| provider.transcribe(&audio, name)).await\n    }\n    other => other,\n}","preventionTips":["Limit concurrent AssemblyAI transcriptions — poll bursts trip 429","Retry whole-job on poll failures; the job usually succeeds on the second attempt","Watch for 404 in poll errors: it means the key/account pairing is wrong, not a transient fault"],"tags":["assemblyai","polling","http-status","transcription","transient"],"backgroundTag":"speech-to-text-api-error","analyzedSha":"88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc","analyzedAt":"2026-08-23T01:07:41.857Z","schemaVersion":2},"datasetVersion":"2026-08-23T08:06:27.607Z"}