nexu-io/open-design · error · Error
grok poll non-JSON: ${truncate(pollText, 200)}
Error message
grok poll non-JSON: ${truncate(pollText, 200)} What it means
Thrown when a Grok poll returned 2xx but the body failed JSON.parse. The poll endpoint returned a non-JSON payload (HTML, empty, plain text) with a success status. The message includes the first 200 chars (truncated) so the operator can identify the unexpected content. Distinct from [474] which fires on non-2xx status.
Source
Thrown at apps/daemon/src/media/index.ts:2382
: 8 * 60 * 1000;
if (typeof onProgress === 'function') {
const mode = ctx.imageRef ? 'i2v' : 't2v';
onProgress(`grok ${mode} task ${requestId} accepted; polling status…`);
}
while (Date.now() - startedAt < maxMs) {
await sleep(4000);
const pollResp = await fetch(`${baseUrl}/videos/${encodeURIComponent(requestId)}`, withMediaRequestInit(ctx, {
headers: { 'authorization': `Bearer ${credentials.apiKey}` },
}));
const pollText = await pollResp.text();
if (!pollResp.ok) {
throw new Error(`grok poll ${pollResp.status}: ${truncate(pollText, 240)}`);
}
let pollData: any;
try {
pollData = JSON.parse(pollText);
} catch {
throw new Error(`grok poll non-JSON: ${truncate(pollText, 200)}`);
}
lastStatus = pollData.status || '';
if (typeof onProgress === 'function') {
const elapsedSec = Math.round((Date.now() - startedAt) / 1000);
onProgress(`grok task ${requestId} status=${lastStatus || 'pending'} (elapsed ${elapsedSec}s)`);
}
if (lastStatus === 'done' || lastStatus === 'succeeded') {
videoUrl = pollData?.video?.url || null;
break;
}
if (lastStatus === 'failed' || lastStatus === 'expired') {
const reasonRaw = pollData?.error?.message || pollData?.error || lastStatus;
const reason = typeof reasonRaw === 'string' ? reasonRaw : JSON.stringify(reasonRaw);
throw new Error(`grok task ${lastStatus}: ${reason}`);
}
}
// Loop exited without a videoUrl. Distinguish the two reachable
// cases so operators know which lever to pull: bumping the pollView on GitHub (pinned to 5be4028344)
Solutions
- Inspect the truncated pollText in the error — HTML/doctype indicates a gateway page; the loop would have tolerated a retry if the parse error didn't throw.
- Patch the loop to tolerate transient non-JSON (continue instead of throw) within the poll ceiling, then retry.
- If persistent, verify baseUrl and network path; capture full response and report to xAI.
- Retry the entire job — transient gateway blips usually don't recur.
Example fix
// before
try {
pollData = JSON.parse(pollText);
} catch {
throw new Error(`grok poll non-JSON: ${truncate(pollText, 200)}`);
}
// after — tolerate transient non-JSON within the ceiling
try {
pollData = JSON.parse(pollText);
} catch {
if (Date.now() - startedAt < maxMs) { await sleep(4000); continue; }
throw new Error(`grok poll non-JSON: ${truncate(pollText, 200)}`);
} Defensive patterns
Strategy: retry
Try / catch
// Non-JSON poll responses are usually transient gateway blips — tolerate them
// inside the ceiling, only throw when time is up.
try {
pollData = JSON.parse(pollText);
} catch {
if (Date.now() - startedAt < maxMs) { await sleep(4000); continue; }
throw new Error(`grok poll non-JSON: ${truncate(pollText, 200)}`);
} Prevention
- Don't let a single non-JSON poll response abort a multi-minute job — continue inside the ceiling.
- Log non-JSON occurrences so you can detect a rising gateway-error rate without losing jobs.
- Send `Accept: application/json` on polls to discourage HTML interstitials.
When it happens
Trigger: pollResp.ok is true but JSON.parse(pollText) throws — xAI or an intermediary returned 200 with HTML/empty/plain text during a poll iteration. Usually a transient gateway artifact.
Common situations: Cloudflare challenge served mid-poll; xAI gateway returning a cached HTML error during maintenance; reverse-proxy rewriting; transient empty 200 responses under load.
Related errors
- grok video non-JSON: ${truncate(submitText, 200)}
- grok poll ${pollResp.status}: ${truncate(pollText, 240)}
- no xAI credentials — sign in with your SuperGrok subscriptio
- grok image ${resp.status}: ${truncate(text, 240)}
- grok image non-JSON: ${truncate(text, 200)}
AI-assisted analysis of nexu-io/open-design@5be4028344 (2026-08-12).
Data as JSON: /api/errors/9a27ce6876ac5a95.
Report an issue: GitHub.