nexu-io/open-design · error · Error

grok video submit returned no inline video and no request_id

Error message

grok video submit returned no inline video and no request_id to poll (status=${lastStatus || 'unknown'})

What it means

Thrown when the Grok submit step returned 2xx JSON but neither an inline video.url nor a pollable id (requestId). xAI's documented contract is either (a) finished video inline, or (b) {id, status:'pending'} stub to poll; getting neither is an upstream contract break. The message interpolates the last observed status (from submitData.status) to help pinpoint whether the response was malformed or a new shape.

Source

Thrown at apps/daemon/src/media/index.ts:2419

    // ceiling (timeout) vs filing a bug against the upstream contract
    // (status=done but no video.url).
    if (!videoUrl) {
      const elapsedSec = Math.round((Date.now() - startedAt) / 1000);
      const ceilingSec = Math.round(maxMs / 1000);
      throw new Error(
        `grok video timed out after ${elapsedSec}s waiting for status=done `
        + `(last status: ${lastStatus || 'pending'}, ceiling ${ceilingSec}s). `
        + `If your jobs legitimately need longer, raise OD_GROK_VIDEO_MAX_POLL_MS.`,
      );
    }
  }

  if (!videoUrl) {
    // Submit returned neither an inline video.url nor a request_id —
    // upstream broke its own contract. Surfacing the last status helps
    // pinpoint whether it was a transient API blip or a malformed
    // response we should add a parser branch for.
    throw new Error(
      `grok video submit returned no inline video and no request_id to poll `
      + `(status=${lastStatus || 'unknown'})`,
    );
  }

  const dlResp = await fetch(videoUrl, withMediaRequestInit(ctx));
  if (!dlResp.ok) throw new Error(`grok video fetch ${dlResp.status}`);
  const arr = await dlResp.arrayBuffer();
  const bytes = Buffer.from(arr);

  return {
    bytes,
    providerNote: `grok/${ctx.wireModel} · ${aspectRatio} · ${durationSec}s · ${bytes.length} bytes`,
    suggestedExt: '.mp4',
  };
}

function grokAspectFor(aspect?: string): string {

View on GitHub (pinned to 5be4028344)

Solutions

  1. Reproduce the submit call with curl to capture the full response body and identify the new shape.
  2. If xAI added a new field for the pollable id, extend the extraction (submitData?.id || submitData?.request_id || submitData?.<newField>) in apps/daemon/src/media/index.ts around line ~2356.
  3. Confirm baseUrl points at the xAI API version your code targets.
  4. Retry once — a transient malformed response may not recur; if it does, file an xAI support ticket with the captured body.

Example fix

// before
const requestId = submitData?.id || submitData?.request_id || null;

// after — accept new shape + aid diagnosis
const requestId =
  submitData?.id || submitData?.request_id || submitData?.data?.id || null;
if (!videoUrl && !requestId) {
  throw new Error(
    `grok video submit returned no inline video and no request_id to poll `
    + `(status=${lastStatus || 'unknown'}, body=${truncate(JSON.stringify(submitData), 240)})`,
  );
}
Defensive patterns

Strategy: type-guard

Type guard

// Narrow the parsed Grok submit response so a missing video+id is caught at the
// boundary with a typed, debuggable error.
interface GrokSubmitInline { video: { url: string }; status: string }
interface GrokSubmitPollable { id: string; status: string }
interface GrokSubmitRequestId { request_id: string; status: string }
function getGrokRequestId(d: unknown): string | null {
  if (!d || typeof d !== 'object') return null;
  const obj = d as Record<string, any>;
  return (typeof obj.id === 'string' && obj.id) || (typeof obj.request_id === 'string' && obj.request_id) || null;
}
function getGrokInlineVideoUrl(d: unknown): string | null {
  if (!d || typeof d !== 'object') return null;
  const obj = d as Record<string, any>;
  return (typeof obj.video?.url === 'string' && obj.video.url) || null;
}

Try / catch

let videoUrl = getGrokInlineVideoUrl(submitData);
const requestId = getGrokRequestId(submitData);
if (!videoUrl && !requestId) {
  throw new Error(
    `grok video submit returned no inline video and no request_id to poll `
    + `(status=${(submitData as any)?.status || 'unknown'}, body=${truncate(JSON.stringify(submitData), 240)})`,
  );
}

Prevention

When it happens

Trigger: submitData parses OK but submitData.video.url, submitData.id, and submitData.request_id are all falsy. Happens if xAI ships an API change introducing a third response shape, or returns a soft-success with neither asset.

Common situations: xAI API version mismatch (baseUrl pinned to an older/newer version); xAI adds a new asynchronous handshake shape; malformed response from an upstream bug; an intermediate proxy rewriting the response.

Related errors


AI-assisted analysis of nexu-io/open-design@5be4028344 (2026-08-12). Data as JSON: /api/errors/7fd53883831fa225. Report an issue: GitHub.