nexu-io/open-design · error · Error
volcengine poll ${pollResp.status}: ${truncate(pollText, 240
Error message
volcengine poll ${pollResp.status}: ${truncate(pollText, 240)} What it means
Thrown when polling `GET /api/v3/contents/generations/tasks/{id}` returns a non-2xx status. Unlike creation failures, a poll failure is often transient (rate-limited polling, momentary 5xx), so the status+body are surfaced for triage.
Source
Thrown at apps/daemon/src/media/index.ts:1488
let lastStatus = '';
// Emit a "task accepted" line right away so the agent's chat shows
// something within the first second instead of going silent for the
// full poll loop. cc's Bash tool considers a long-quiet pipe stuck
// and times out at ~2 minutes — Volcengine i2v routinely takes
// 3-5 minutes, so without this stream, every i2v dispatch dies
// mid-flight.
if (typeof onProgress === 'function') {
const mode = ctx.imageRef ? 'i2v' : 't2v';
onProgress(`volcengine ${mode} task ${taskId} accepted; polling status…`);
}
while (Date.now() - startedAt < maxMs) {
await sleep(4000);
const pollResp = await fetch(`${baseUrl}/contents/generations/tasks/${encodeURIComponent(taskId)}`, withMediaRequestInit(ctx, {
headers: { 'authorization': `Bearer ${credentials.apiKey}` },
}));
const pollText = await pollResp.text();
if (!pollResp.ok) {
throw new Error(`volcengine poll ${pollResp.status}: ${truncate(pollText, 240)}`);
}
let pollData: any;
try {
pollData = JSON.parse(pollText);
} catch {
throw new Error(`volcengine poll non-JSON: ${truncate(pollText, 200)}`);
}
lastStatus = pollData.status || '';
// Forward each poll tick. Heartbeat doubles as a "command is alive"
// signal for the agent's bash tool — the daemon's SSE stream emits
// an event for every line, which cc renders into the chat as live
// output so its watchdog never marks the call as hung.
if (typeof onProgress === 'function') {
const elapsedSec = Math.round((Date.now() - startedAt) / 1000);
onProgress(`volcengine task ${taskId} status=${lastStatus || 'pending'} (elapsed ${elapsedSec}s)`);
}
if (lastStatus === 'succeeded') {
videoUrl = pollData?.content?.video_url || null;View on GitHub (pinned to 5be4028344)
Solutions
- Retry the whole render — transient poll 5xx/429 usually clear on the next attempt.
- If consistently 429, the 4s poll interval may exceed the tier's allowance; reduce concurrency.
- On 401/404, restart with a fresh key — the task id is no longer usable.
Defensive patterns
Strategy: retry
Try / catch
// Poll failures are usually transient — retry the whole render once.
try {
return await renderVolcengineVideo(ctx, credentials, onProgress);
} catch (err) {
const msg = err instanceof Error ? err.message : String(err);
if (/poll 5\d{2}|poll 429/.test(msg)) { return await renderVolcengineVideo(ctx, credentials, onProgress); }
throw err;
} Prevention
- Treat mid-render poll 5xx/429 as retryable, not fatal.
- Watch for keys invalidated mid-render on long i2v tasks.
- Keep concurrency low enough to stay under the ARK tier's poll allowance.
When it happens
Trigger: `pollResp.ok === false` during the 4-second-interval poll loop. Causes: 429 from polling too aggressively for the account tier, 401 from a key invalidated mid-render, 404 if the task id expired, or transient 5xx from the Ark service.
Common situations: (1) Polling rate limit on lower ARK tiers; (2) long-running i2v task outliving key validity; (3) transient Volcengine 5xx mid-render.
Related errors
- volcengine task create ${taskResp.status}: ${truncate(taskTe
- volcengine poll non-JSON: ${truncate(pollText, 200)}
- volcengine task ${lastStatus}: ${reason}
- volcengine task did not finish in time (last status: ${lastS
- volcengine video fetch ${dlResp.status}
AI-assisted analysis of nexu-io/open-design@5be4028344 (2026-08-12).
Data as JSON: /api/errors/047655b0c7cefa66.
Report an issue: GitHub.